查看: 5373|回复: 21

[有事请教] 为什么push进去都是undifineied

[复制链接]
梦石
0
星屑
1919
在线时间
404 小时
注册时间
2014-7-7
回帖
209

开拓者

发表于 2020-9-22 00:01:47 | 显示全部楼层 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有账号?注册会员

×
本帖最后由 kklt 于 2020-9-23 11:04 编辑

[pre lang="javascript"]var runningSum = function (nums, list = [], i = 0, ) {
    if (i == 0) {
        list.push(nums)
        runningSum(nums, list, i+=1)
    } else {
        
        list.push(george(nums,i) )
        if (i == nums.length) {
            return list
        }
    }
    runningSum(nums, list, i+=1)

   
};
function george(nums,i,sum = 0,b = i) {
   
    if (b == 0) {
        return sum
    }
    if (b < nums.length){
        sum += nums[i-=1]
    }
    george(nums,i,sum)
}
var temp = runningSum([1, 2, 3, 4, 5])
console.log(temp)[/pre]


我想实现一个数组和的实现,就是接受一个数组,返回一个每项都是前所有项的和的数组。
但是为什么当我把george()push进list确是undifined。
cheap

梦石
1
星屑
23236
在线时间
9564 小时
注册时间
2012-6-19
回帖
7018

开拓者短篇九导演组冠军

发表于 2020-9-22 00:12:50 | 显示全部楼层
第24行,你倒是return啊
回复

使用道具 举报

梦石
0
星屑
1919
在线时间
404 小时
注册时间
2014-7-7
回帖
209

开拓者

 楼主| 发表于 2020-9-22 00:13:58 | 显示全部楼层

第19行那个return sum 不能吗
cheap
回复

使用道具 举报

梦石
0
星屑
1919
在线时间
404 小时
注册时间
2014-7-7
回帖
209

开拓者

 楼主| 发表于 2020-9-22 00:18:44 | 显示全部楼层
喵呜喵5 发表于 2020-9-22 00:12
第24行,你倒是return啊


有点不太懂。。
那个。return sum 难道不是就是把sum返回然后终止函数吗。
为什么后面还要return george。
cheap
回复

使用道具 举报

梦石
1
星屑
23236
在线时间
9564 小时
注册时间
2012-6-19
回帖
7018

开拓者短篇九导演组冠军

发表于 2020-9-22 00:38:38 | 显示全部楼层
kklt 发表于 2020-9-22 00:18
有点不太懂。。
那个。return sum 难道不是就是把sum返回然后终止函数吗。
为什么后面还要return george ...

因为你在 george (b != 0) 里面又执行了一个 george (b == 0),
return sum 结束了 george (b == 0),但并没有结束 george (b != 0)

你可以去了解一下“递归”,或者,别用这种实现方式,换其他写法

  1. var runningSum = function (nums) {
  2.   var result = []
  3.   nums.forEach((number, index)=>{
  4.     if (index === 0){
  5.       result[index] = number
  6.     }else{
  7.       result[index] = result[index - 1] + number
  8.     }
  9.   })
  10.   return result
  11. }

  12. var temp = runningSum([1, 2, 3, 4, 5])
  13. console.log(temp)
复制代码



回复

使用道具 举报

梦石
0
星屑
13562
在线时间
2753 小时
注册时间
2014-10-4
回帖
705

R考场第七期纪念奖

发表于 2020-9-22 01:13:11 | 显示全部楼层
你在学js吧..感觉各种东西都有 代码写的比较神奇
js中假如不指定返回值就会返回undefined
举一个很简单的例子
[pre lang="javascript"]function t(i){
    if(i==0){
        return 0
    }
    t(i-1)
}
console.log(t(1))
[/pre]
你觉得会输出0对吧?
但是为什么却是undefined呢
因为虽然最内层的调用返回了0 但是到外面一层也就是 t(1) 时却什么也不返回
应该被返回的0直接就被丢掉了
return确实是终止了函数 但是结束的是t(0) 而不是t(1)
递归调用 每一层都是一个"新"的函数在执行 需要一层层返回 而不会一下子回到最外层

[pre lang="javascript"]var runningSum = function (nums, list = [], i = 0, ) {
    if (i == 0) {
        //list.push(nums)
        return runningSum(nums, list, i+=1)
    } else {

        list.push(george(nums,i) )
        if (i == nums.length) {
            return list
        }
    }
    return runningSum(nums, list, i+=1)


};
function george(nums,i,sum = 0,b = i) {
    if (b == 0) {
        return sum
    }
    if (b <= nums.length){
        sum += nums[i-=1]
    }
    return george(nums,i,sum)
}
var temp = runningSum([1, 2, 3, 4, 5])
console.log(temp)
[/pre]

小改了你的代码
加了一些 return以确保返回值的传递
注释的那行是多余的 因为重复输出了
20行改成了 <= 不然就炸了
回复

使用道具 举报

梦石
0
星屑
1919
在线时间
404 小时
注册时间
2014-7-7
回帖
209

开拓者

 楼主| 发表于 2020-9-22 01:35:20 | 显示全部楼层
喵呜喵5 发表于 2020-9-22 00:38
因为你在 george (b != 0) 里面又执行了一个 george (b == 0),
return sum 结束了 george (b == 0),但 ...

感谢。
就是说sum其实是被return到了上层的grogre,
除了b==1的geogre,
其他geogre都没有返回值,
所以是undifined。

改了一下,这样就行了。
  1. var runningSum = function (nums, list = [], i = 0, ) {
  2.     if (i == 0) {
  3.         return runningSum(nums, list, i += 1)
  4.     } else {
  5.         console.log('up' + i)
  6.         list.push(george(nums, i))

  7.         if (i == nums.length) {
  8.             return list
  9.         }
  10.     }
  11.     console.log('down' + i)
  12.     return runningSum(nums, list, i += 1)

  13. };

  14. function george(nums, ig, sum = 0, b = ig) {

  15.     if (b == 0) {
  16.         return sum
  17.     }
  18.     if (b <= nums.length) {
  19.         sum += nums[ig -= 1]
  20.         return george(nums, ig, sum)
  21.     }

  22. }
  23. var temp = runningSum([1, 2])
  24. console.log(temp)
复制代码
cheap
回复

使用道具 举报

梦石
0
星屑
1919
在线时间
404 小时
注册时间
2014-7-7
回帖
209

开拓者

 楼主| 发表于 2020-9-22 01:43:30 | 显示全部楼层
SixRC 发表于 2020-9-22 01:13
你在学js吧..感觉各种东西都有 代码写的比较神奇
js中假如不指定返回值就会返回undefined
举一个很简单的例 ...


啊哈,编辑的时候没看见你的回复。
(要是早点刷新就好了,省了我自己一个人大半天功夫。)
总之多谢啦。
我的确在学js,和《sicp》同时在学,里面用的是lisp(以前也学过一些ruby)
就和你说的一样,我把它们混淆在一起了。。
现在算是清楚了。

点评

上面"写在一起或单独写出来"其实想表达的是一个意思 我头疼了  发表于 2020-9-22 02:55
总结就是 runningsum=foreach+sum 先写一个foreach 再写一个sum 最后拼起来 大概就是那种感觉了  发表于 2020-9-22 02:50
假如解决一个问题需要子步骤A与B 我想重要的是对它们的分离吧 对一个部分的实现不影响另一部分 而不是写在一起或单独写出来 而是一切可复用 这样?  发表于 2020-9-22 02:45
但我想 喵呜喵5写的更 em 有那种感觉 就是分解问题 对数组整体f(x) 得到结果  发表于 2020-9-22 02:32
没看过sicp 曾经接触过函数式编程 你的版本虽然避开了循环 但实际上有一种用递归模拟循环的感觉 整体思路依旧是对每个位置 计算并放入和  发表于 2020-9-22 02:30
cheap
回复

使用道具 举报

梦石
0
星屑
1919
在线时间
404 小时
注册时间
2014-7-7
回帖
209

开拓者

 楼主| 发表于 2020-9-26 21:52:14 | 显示全部楼层
本帖最后由 kklt 于 2020-9-26 21:56 编辑
SixRC 发表于 2020-9-22 01:13
你在学js吧..感觉各种东西都有 代码写的比较神奇
js中假如不指定返回值就会返回undefined
举一个很简单的例 ...


确实。
递归模拟循环。
其实,我这么写也是因为产生过的以下想法:
如果递归循环看作操作符”jump“的一种,那它们似乎就那样没太大差别了。

你说的”写在一起或单独写出来"(但愿没有理解错‘我头疼了’的含义)
就我所知道的知识,我可以拿来谈一谈。

在lisp中foreach这样定义(感觉js应该也差不多)。
写成js的话大概是这样。
(浆糊代码。如果有更好的模拟方法,欢迎碾压。
本来想写一个对于数组的类似cdr car,结果写出来感觉不太好。那就手工实现一个cons吧。
如果不太了解这些lisp的词汇,看了下面的代码就应该知道了)

[pre lang="javascript"]
//=============================================================================
//js 模拟 cons  使用array版本(lisp有单项链表list,写法是用()包起来的一组数。用array主要是想在语法上能和lisp有点衔接,既用array来表示list)
//=============================================================================
let Cons = function (left=‘undefined’, right = 'undfined') {
    this.car = left;
    this.cdr = right;
}


function itemToCons(array) {
    //let ineerarray = array.slice(0);
    array.forEach((v,i,a) => {
        a = new Cons(a);
    });
    return array;

}

function combineCons(array) {
    //let ineerarray = array.slice(0)
    array.forEach((v,i,a) => {
        if (i <= a.length - 1 -1  ){
            a[a.length - i-1-1].cdr = a[a.length - i-1]
        }
    });
}


function arrayToCons(array) {
    combineCons(itemToCons(array))
    return array
}

function getlist(array) {
    if (array[0]){
        return array[0]
    }else return array;
}
//foreach
function fooeach(something, f) {
   
        if (!getlist(something).cdr){
            return
        }
        getlist(something).car = f(getlist(something).car)
        return fooeach(getlist(something).cdr,f)

}
asd = [1,2,3,4,5]

fooeach(arrayToCons(asd), function (i) {return i*2})
console.log(asd)[/pre]

就如上所述。
foreach和之前写的那串合在一起的代码。
它们相同点地方都是:获取 ’‘ 数组 ’‘ 信息+条件判断+jump。
如果把runsum抽象出来,再给它的参数列表里加上回调函数,就是foreach。
george就是传入的回调。







点评

不了解lisp 所以不评价了 不过递归和循环的差别可大了 概念存在 则有意义 ;js也非lisp 写出符合js特性的代码会更好吧; 求同存异就好  发表于 2020-9-27 03:30
cheap
回复

使用道具 举报

梦石
0
星屑
1919
在线时间
404 小时
注册时间
2014-7-7
回帖
209

开拓者

 楼主| 发表于 2020-9-27 11:37:48 | 显示全部楼层
本帖最后由 kklt 于 2020-9-27 13:27 编辑
SixRC 发表于 2020-9-22 01:13
你在学js吧..感觉各种东西都有 代码写的比较神奇
js中假如不指定返回值就会返回undefined
举一个很简单的例 ...


抱歉,我没有讲清楚。
我为什么说循环和递归差别不大呢?看这里。(伪代码)
这里变量就都当作传引用的把。

用jump写的循环。
a = 1
:asd
a++
jump :asd

这里就是不断循环执行a++。

现在这样写.
a=1
func(num){
    num++
   func(num);
}
func(a)

效果相同。
不同点(Maybe)
循环应该是一种单一的过程。
在执行过程,数据不断执行这些过程,内存上不会有太大变化。
也就是jump到循环开始。如果有终止条件的话就直接jump出来。

递归的话,一是保存外层函数的环境,一是不断在创建的函数环境创建函数环境。所以内存占用也会更多。
也就是jump到新创建的函数体。如果有返回的话最终逐函数jump出来
然后我这样写。


a=1
b=0
:asd
if a/2==0 a++
jump :bsd
jump :asd
:bsd
b+=a
jump :asd

跳转的:bsd,是不是像像进入一个新环境?
是不是看起来越来越像递归?
对比下面:

a=1
b=0
func (num){

  if (a/2==0)  func(a++)
   b+num
}
func(a)

所以我说,循环递归都是jump。
都是有限制的jump。
有限制的jump虽然降低了灵活性,但却提升了可靠性。
cheap
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部