douglascrockford / howjavascriptworks

Programs from the book _How JavaScript Works_
319 stars 53 forks source link

Update neo.runtime.js #10

Closed const-chris closed 5 years ago

const-chris commented 5 years ago

I think in order for the array constructor to work as intended, there needs to be logic checking if the first argument is an array and the second argument is a function. If so, the second argument is used as a mapping function across the first argument.

douglascrockford commented 5 years ago

Thanks for the suggestion. The functionality you are proposing is provided by map. I don't think it is necessary for array to do it too, although it makes some sense.

 If the argu­ment is an array, then make a shallow copy of the array. Addi­tional argu­ments can give the starting and ending posi­tions for copying a por­tion of the array.
const-chris commented 5 years ago

Ok, I must have misunderstood something.

I thought this was the expected functionality based on the example code on page 28.9: var processed: array(arguments, prepare arguments)

The example transpiles for me without an issue, but if I try to run it with the runtime code unaltered, it fails. With the change I suggested, I can run the example code and get the expected results.

I’m sure you’re very busy, but if you have any idea what I’m doing wrong, I’d really appreciate your feedback.

This is the js I used for testing:

import $NEO from './neo.runtime.js';
import codegen from './neo.codegen.js';
import parse from './neo.parse.js';
import tokenize from './neo.tokenize.js';
import big_float from './big_float.js';

function neo(source) {
  return codegen(parse(tokenize(source)));
}

const neo_do = neo(`
export ƒ function, arguments... {
    if length(arguments) = 0
        return null
    var index: 0
    def result: []
    var stop: false

    def prepare arguments: ƒ argument {
        def candidate: (
            array?(argument)
            ? argument[index]
            ! (
                function?(argument)
                ? argument
                ! argument
            )
        )
        if candidate = null
            let stop: true
        return candidate
    }

    loop
        var processed: array(arguments, prepare arguments)
        if stop
            break
        let result[]: function(processed...)
        let index: index + 1
    return result
}
`);

// console.log(neo_do);

const $do = eval(neo_do);

const $1 = $NEO.number("1")
const $2 = $NEO.number("2")
const $3 = $NEO.number("3")
const $4 = $NEO.number("4")
const $5 = $NEO.number("5")
const $6 = $NEO.number("6")
const $60 = $NEO.number("60")

let result = $do($NEO.add, [$1, $2, $3], [$5, $4, $3]);

console.log(result.map(big_float.number))

result = $do($NEO.div, $60, [$1, $2, $3, $4, $5, $6]);

console.log(result.map(big_float.normalize).map(big_float.number))

Really enjoyed the book, btw.

douglascrockford commented 5 years ago

I have adopted your suggestion. Thanks.