设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 4168|回复: 21
打印 上一主题 下一主题

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

[复制链接]

Lv3.寻梦者

梦石
0
星屑
1859
在线时间
396 小时
注册时间
2014-7-7
帖子
264

开拓者

跳转到指定楼层
1
发表于 2020-9-22 00:01:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

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

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

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

JAVASCRIPT 代码复制
  1. var runningSum = function (nums, list = [], i = 0, ) {
  2.     if (i == 0) {
  3.         list.push(nums[i])
  4.         runningSum(nums, list, i+=1)
  5.     } else {
  6.  
  7.         list.push(george(nums,i) )
  8.         if (i == nums.length) {
  9.             return list
  10.         }
  11.     }
  12.     runningSum(nums, list, i+=1)
  13.  
  14.  
  15. };
  16. function george(nums,i,sum = 0,b = i) {
  17.  
  18.     if (b == 0) {
  19.         return sum
  20.     }
  21.     if (b < nums.length){
  22.         sum += nums[i-=1]
  23.     }
  24.     george(nums,i,sum)
  25. }
  26. var temp = runningSum([1, 2, 3, 4, 5])
  27. console.log(temp)



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

Lv5.捕梦者 (暗夜天使)

只有笨蛋才会看到

梦石
1
星屑
21631
在线时间
9414 小时
注册时间
2012-6-19
帖子
7118

开拓者短篇九导演组冠军

2
发表于 2020-9-22 00:12:50 | 只看该作者
第24行,你倒是return啊
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
1859
在线时间
396 小时
注册时间
2014-7-7
帖子
264

开拓者

3
 楼主| 发表于 2020-9-22 00:13:58 | 只看该作者

第19行那个return sum 不能吗
take is cheap
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
1859
在线时间
396 小时
注册时间
2014-7-7
帖子
264

开拓者

4
 楼主| 发表于 2020-9-22 00:18:44 | 只看该作者
喵呜喵5 发表于 2020-9-22 00:12
第24行,你倒是return啊


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

使用道具 举报

Lv5.捕梦者 (暗夜天使)

只有笨蛋才会看到

梦石
1
星屑
21631
在线时间
9414 小时
注册时间
2012-6-19
帖子
7118

开拓者短篇九导演组冠军

5
发表于 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)
复制代码



回复 支持 反对

使用道具 举报

Lv4.逐梦者

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

R考场第七期纪念奖

6
发表于 2020-9-22 01:13:11 | 只看该作者
你在学js吧..感觉各种东西都有 代码写的比较神奇
js中假如不指定返回值就会返回undefined
举一个很简单的例子
JAVASCRIPT 代码复制
  1. function t(i){
  2.     if(i==0){
  3.         return 0
  4.     }
  5.     t(i-1)
  6. }
  7. console.log(t(1))

你觉得会输出0对吧?
但是为什么却是undefined呢
因为虽然最内层的调用返回了0 但是到外面一层也就是 t(1) 时却什么也不返回
应该被返回的0直接就被丢掉了
return确实是终止了函数 但是结束的是t(0) 而不是t(1)
递归调用 每一层都是一个"新"的函数在执行 需要一层层返回 而不会一下子回到最外层

JAVASCRIPT 代码复制
  1. var runningSum = function (nums, list = [], i = 0, ) {
  2.     if (i == 0) {
  3.         //list.push(nums[i])
  4.         return runningSum(nums, list, i+=1)
  5.     } else {
  6.  
  7.         list.push(george(nums,i) )
  8.         if (i == nums.length) {
  9.             return list
  10.         }
  11.     }
  12.     return runningSum(nums, list, i+=1)
  13.  
  14.  
  15. };
  16. function george(nums,i,sum = 0,b = i) {
  17.     if (b == 0) {
  18.         return sum
  19.     }
  20.     if (b <= nums.length){
  21.         sum += nums[i-=1]
  22.     }
  23.     return george(nums,i,sum)
  24. }
  25. var temp = runningSum([1, 2, 3, 4, 5])
  26. console.log(temp)


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

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
1859
在线时间
396 小时
注册时间
2014-7-7
帖子
264

开拓者

7
 楼主| 发表于 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)
复制代码
take is cheap
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
1859
在线时间
396 小时
注册时间
2014-7-7
帖子
264

开拓者

8
 楼主| 发表于 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
take is cheap
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
1859
在线时间
396 小时
注册时间
2014-7-7
帖子
264

开拓者

9
 楼主| 发表于 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的词汇,看了下面的代码就应该知道了)

JAVASCRIPT 代码复制
  1. //=============================================================================
  2. //js 模拟 cons  使用array版本(lisp有单项链表list,写法是用()包起来的一组数。用array主要是想在语法上能和lisp有点衔接,既用array来表示list)
  3. //=============================================================================
  4. let Cons = function (left=‘undefined’, right = 'undfined') {
  5.     this.car = left;
  6.     this.cdr = right;
  7. }
  8.  
  9.  
  10. function itemToCons(array) {
  11.     //let ineerarray = array.slice(0);
  12.     array.forEach((v,i,a) => {
  13.         a[i] = new Cons(a[i]);
  14.     });
  15.     return array;
  16.  
  17. }
  18.  
  19. function combineCons(array) {
  20.     //let ineerarray = array.slice(0)
  21.     array.forEach((v,i,a) => {
  22.         if (i <= a.length - 1 -1  ){
  23.             a[a.length - i-1-1].cdr = a[a.length - i-1]
  24.         }
  25.     });
  26. }
  27.  
  28.  
  29. function arrayToCons(array) {
  30.     combineCons(itemToCons(array))
  31.     return array
  32. }
  33.  
  34. function getlist(array) {
  35.     if (array[0]){
  36.         return array[0]
  37.     }else return array;
  38. }
  39. //foreach
  40. function fooeach(something, f) {
  41.  
  42.         if (!getlist(something).cdr){
  43.             return
  44.         }
  45.         getlist(something).car = f(getlist(something).car)
  46.         return fooeach(getlist(something).cdr,f)
  47.  
  48. }
  49. asd = [1,2,3,4,5]
  50.  
  51. fooeach(arrayToCons(asd), function (i) {return i*2})
  52. console.log(asd)


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







点评

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

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
1859
在线时间
396 小时
注册时间
2014-7-7
帖子
264

开拓者

10
 楼主| 发表于 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虽然降低了灵活性,但却提升了可靠性。
take is cheap
回复 支持 反对

使用道具 举报

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

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-11-16 09:38

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表