Patch 9.0.0615
Problem:    Using reduce() on a list from range() is a bit slow.
Solution:   Avoid materializing the list.
Files:      src/list.c, src/testdir/test_listdict.vim


*** ../vim-9.0.0614/src/list.c  2022-09-22 17:06:56.295037465 +0100
--- src/list.c  2022-09-28 12:56:19.060434241 +0100
***************
*** 2377,2385 ****
        rettv->v_type = VAR_LIST;
        rettv->vval.v_list = NULL;
      }
!     if (l == NULL
!           || (filtermap == FILTERMAP_FILTER
!               && value_check_lock(l->lv_lock, arg_errmsg, TRUE)))
        return;
  
      prev_lock = l->lv_lock;
--- 2377,2384 ----
        rettv->v_type = VAR_LIST;
        rettv->vval.v_list = NULL;
      }
!     if (l == NULL || (filtermap == FILTERMAP_FILTER
!                           && value_check_lock(l->lv_lock, arg_errmsg, TRUE)))
        return;
  
      prev_lock = l->lv_lock;
***************
*** 3011,3038 ****
  {
      list_T    *l = argvars[0].vval.v_list;
      listitem_T  *li = NULL;
      typval_T  initial;
      typval_T  argv[3];
      int               r;
      int               called_emsg_start = called_emsg;
      int               prev_locked;
  
!     if (l != NULL)
!       CHECK_LIST_MATERIALIZE(l);
      if (argvars[2].v_type == VAR_UNKNOWN)
      {
!       if (l == NULL || l->lv_first == NULL)
        {
            semsg(_(e_reduce_of_an_empty_str_with_no_initial_value), "List");
            return;
        }
!       initial = l->lv_first->li_tv;
!       li = l->lv_first->li_next;
      }
      else
      {
        initial = argvars[2];
!       if (l != NULL)
            li = l->lv_first;
      }
      copy_tv(&initial, rettv);
--- 3010,3053 ----
  {
      list_T    *l = argvars[0].vval.v_list;
      listitem_T  *li = NULL;
+     int               range_list;
+     int               range_idx = 0;
+     varnumber_T       range_val = 0;
      typval_T  initial;
      typval_T  argv[3];
      int               r;
      int               called_emsg_start = called_emsg;
      int               prev_locked;
  
!     // Using reduce on a range() uses "range_idx" and "range_val".
!     range_list = l != NULL && l->lv_first == &range_list_item;
!     if (range_list)
!       range_val = l->lv_u.nonmat.lv_start;
! 
      if (argvars[2].v_type == VAR_UNKNOWN)
      {
!       if (l == NULL || l->lv_len == 0)
        {
            semsg(_(e_reduce_of_an_empty_str_with_no_initial_value), "List");
            return;
        }
!       if (range_list)
!       {
!           initial.v_type = VAR_NUMBER;
!           initial.vval.v_number = range_val;
!           range_val += l->lv_u.nonmat.lv_stride;
!           range_idx = 1;
!       }
!       else
!       {
!           initial = l->lv_first->li_tv;
!           li = l->lv_first->li_next;
!       }
      }
      else
      {
        initial = argvars[2];
!       if (l != NULL && !range_list)
            li = l->lv_first;
      }
      copy_tv(&initial, rettv);
***************
*** 3041,3060 ****
        return;
  
      prev_locked = l->lv_lock;
- 
      l->lv_lock = VAR_FIXED;  // disallow the list changing here
!     for ( ; li != NULL; li = li->li_next)
      {
        argv[0] = *rettv;
-       argv[1] = li->li_tv;
        rettv->v_type = VAR_UNKNOWN;
  
        r = eval_expr_typval(expr, argv, 2, rettv);
  
        clear_tv(&argv[0]);
        if (r == FAIL || called_emsg != called_emsg_start)
            break;
      }
      l->lv_lock = prev_locked;
  }
  
--- 3056,3091 ----
        return;
  
      prev_locked = l->lv_lock;
      l->lv_lock = VAR_FIXED;  // disallow the list changing here
! 
!     while (range_list ? range_idx < l->lv_len : li != NULL)
      {
        argv[0] = *rettv;
        rettv->v_type = VAR_UNKNOWN;
  
+       if (range_list)
+       {
+           argv[1].v_type = VAR_NUMBER;
+           argv[1].vval.v_number = range_val;
+       }
+       else
+           argv[1] = li->li_tv;
+ 
        r = eval_expr_typval(expr, argv, 2, rettv);
  
        clear_tv(&argv[0]);
        if (r == FAIL || called_emsg != called_emsg_start)
            break;
+ 
+       if (range_list)
+       {
+           range_val += l->lv_u.nonmat.lv_stride;
+           ++range_idx;
+       }
+       else
+           li = li->li_next;
      }
+ 
      l->lv_lock = prev_locked;
  }
  
*** ../vim-9.0.0614/src/testdir/test_listdict.vim       2022-09-22 
17:06:56.299037474 +0100
--- src/testdir/test_listdict.vim       2022-09-28 12:58:36.771957027 +0100
***************
*** 1015,1020 ****
--- 1015,1026 ----
        call assert_equal('x y z', reduce(['x', 'y', 'z'], LSTART acc, val 
LMIDDLE acc .. ' ' .. val LEND))
        call assert_equal(120, range(1, 5)->reduce(LSTART acc, val LMIDDLE acc 
* val LEND))
  
+       call assert_equal(0, range(1)->reduce(LSTART acc, val LMIDDLE acc + val 
LEND))
+       call assert_equal(1, range(2)->reduce(LSTART acc, val LMIDDLE acc + val 
LEND))
+       call assert_equal(3, range(3)->reduce(LSTART acc, val LMIDDLE acc + val 
LEND))
+       call assert_equal(6, range(4)->reduce(LSTART acc, val LMIDDLE acc + val 
LEND))
+       call assert_equal(10, range(5)->reduce(LSTART acc, val LMIDDLE acc + 
val LEND))
+ 
        call assert_equal(1, reduce(0z, LSTART acc, val LMIDDLE acc + val LEND, 
1))
        call assert_equal(1 + 0xaf + 0xbf + 0xcf, reduce(0zAFBFCF, LSTART acc, 
val LMIDDLE acc + val LEND, 1))
        call assert_equal(2 * (2 * 1 + 0xaf) + 0xbf, 0zAFBF->reduce(LSTART acc, 
val LMIDDLE 2 * acc + val LEND, 1))
***************
*** 1038,1043 ****
--- 1044,1050 ----
    vim9 assert_equal({'x': 1, 'y': 1, 'z': 1 }, ['x', 'y', 'z']->reduce((acc, 
val) => extend(acc, {[val]: 1 }), {}))
  
    call assert_fails("call reduce([], { acc, val -> acc + val })", 'E998: 
Reduce of an empty List with no initial value')
+   call assert_fails("call reduce(range(0), { acc, val -> acc + val })", 
'E998: Reduce of an empty List with no initial value')
    call assert_fails("call reduce(0z, { acc, val -> acc + val })", 'E998: 
Reduce of an empty Blob with no initial value')
    call assert_fails("call reduce(test_null_blob(), { acc, val -> acc + val 
})", 'E998: Reduce of an empty Blob with no initial value')
    call assert_fails("call reduce('', { acc, val -> acc + val })", 'E998: 
Reduce of an empty String with no initial value')
*** ../vim-9.0.0614/src/version.c       2022-09-28 11:48:26.677156955 +0100
--- src/version.c       2022-09-28 13:20:48.906575541 +0100
***************
*** 701,702 ****
--- 701,704 ----
  {   /* Add new patch number below this line */
+ /**/
+     615,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
208. Your goals for the future are obtaining a second Gbit connection
        and upgrade your NAS to all SSD

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20220928122359.7B1EF1C044A%40moolenaar.net.

Raspunde prin e-mail lui