Project1

标题: 为什么push进去都是undifineied [打印本页]

作者: kklt    时间: 2020-9-22 00:01
标题: 为什么push进去都是undifineied
本帖最后由 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。
作者: 喵呜喵5    时间: 2020-9-22 00:12
第24行,你倒是return啊
作者: kklt    时间: 2020-9-22 00:13
喵呜喵5 发表于 2020-9-22 00:12
你倒是return啊

第19行那个return sum 不能吗
作者: kklt    时间: 2020-9-22 00:18
喵呜喵5 发表于 2020-9-22 00:12
第24行,你倒是return啊


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

作者: 喵呜喵5    时间: 2020-9-22 00: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)
复制代码




作者: SixRC    时间: 2020-9-22 01:13
你在学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行改成了 <= 不然就炸了

作者: kklt    时间: 2020-9-22 01:35
喵呜喵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)
复制代码

作者: kklt    时间: 2020-9-22 01:43
SixRC 发表于 2020-9-22 01:13
你在学js吧..感觉各种东西都有 代码写的比较神奇
js中假如不指定返回值就会返回undefined
举一个很简单的例 ...


啊哈,编辑的时候没看见你的回复。
(要是早点刷新就好了,省了我自己一个人大半天功夫。)
总之多谢啦。
我的确在学js,和《sicp》同时在学,里面用的是lisp(以前也学过一些ruby)
就和你说的一样,我把它们混淆在一起了。。
现在算是清楚了。
作者: kklt    时间: 2020-9-26 21:52
本帖最后由 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就是传入的回调。








作者: kklt    时间: 2020-9-27 11:37
本帖最后由 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虽然降低了灵活性,但却提升了可靠性。

作者: SixRC    时间: 2020-9-27 14:27
kklt 发表于 2020-9-27 11:37
抱歉,我没有讲清楚。
我为什么说循环和递归差别不大呢?看这里。(伪代码)
这里变量就都当作传引用的把 ...


递归本质并不是jump 而是call和ret
所以递归天然的保存了每一帧的信息
这是它和循环最大的不同
正因为它这个属性 所以很多过程用递归写起来非常自然
但是 我的意思是
假如 递归保存的信息并没有被保存的必要 那为什么要用递归而非循环呢?

并不是说 两个东西有相同点 所以可以随便换着用
重要的是 知道他们有共同点 更应该知道他们有不同点
所以区分对待 所以互相借鉴而不是互相替代

许多编程语言会把没有必要保存过程信息的递归优化成循环 例如尾调用优化
相同的 许多循环算法会人为的利用栈来保存过程信息 达到递归的效果

其实 我是更倾向于循环的
因为循环可以借助栈来达到递归能做的事情
但递归最大的缺点即效率是没办法优化的
不过递归写起来是真的舒服

递归是好 所以学习他的思想 而不是处处用递归
同理对其他
是我的拙见
作者: kklt    时间: 2020-9-27 15:26
本帖最后由 kklt 于 2020-9-27 15:28 编辑
SixRC 发表于 2020-9-27 14:27
递归本质并不是jump 而是call和ret
所以递归天然的保存了每一帧的信息
这是它和循环最大的不同


其实我觉得你说的很到点。

虽然说我这里的jump不是特指汇编里面的jump。
屑特,好吧还是我没讲清楚。
我这里这个jump,
一定要说是属于那里的话:
是来自一款指令式的程序小游戏 human resource manager,
其中不存在call,ret,也没有函数。所以里面的循环都是用jump来实现的
对于汇编,我虽然知道一些,但在你说出call和ret之前我甚至都不知道它们的存在。
我说的jump大概更像是一种组件。将它和一些代码组合,可以实现任何存在重复的问题(甚至以外的问题)
对,因为代码很多时候看起来就像是在跳转,这个跳转的就是我说的jump。
好吧,这确实有点想当然了。
也许可以用jump来写一个不同的版本。
作者: kklt    时间: 2020-9-27 17:06
本帖最后由 kklt 于 2020-9-27 17:41 编辑
SixRC 发表于 2020-9-27 14:27
递归本质并不是jump 而是call和ret
所以递归天然的保存了每一帧的信息
这是它和循环最大的不同

不同的环境给的积木不同 所以没必要必须找到相同的积木去搭 合适的就是最好的 是我一直想表达的意思


yes,yes
我get了。

之前用js仿lisp,是考虑到可能读者不了解lisp。同时也是顺便借机尝试一下这个想法。

我说的jump大概更像是一种组件。将它和一些代码组合,可以实现任何存在重复的问题(甚至以外的问题)


妈淡,果然发言还是要在斟酌一下。
其实这句话,更偏向于指jump的泛用性。。
原话确实读起来会有点模糊。




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1