Question

I have a task and a list of arguments. I'd like to apply the task to the list of arguments. Is the only way to do this by using strings instead of tasks and just concatenating? Basically, I'm looking for the equivalent of apply in other languages.

Was it helpful?

Solution

I came across this problem again, and actually figured out a solution!

to-report listify-task [ tsk num-args ]
  let args (reduce word n-values num-args [ (word " (item " ? " ?)") ])
  report runresult (word "task [ (runresult tsk " args ") ]")
end

This converts a reporter task from something that takes a number of arguments to one that takes a list. You use it like so:

observer> show (runresult (listify-task task [?1 + ?2] 2) [4 5])
observer: 9

apply could be implemented on top of this like:

to-report apply [ tsk args ]
  report (runresult (listify-task tsk length args) args)
end

though it would be somewhat inefficient. Better to store the result of listify-task and the run that whenever you need to.

It essentially creates a task of the following form: task [ (runresult tsk item 0 ? item 1 ? ...)].

OTHER TIPS

Can't be done (except by an extension).

I would support this as an addition to the core language, actually. There would need to be separate prims for command tasks and reporter tasks, just as run and runresult are separate.

Writing them (either as extension prims, or as core prims) wouldn't be very hard; it would only involve writing boilerplate and glue, not any "real" code, and looking at how run and runresult are implemented would show you exactly what to do.

I expanded on this to create a procedure that allows you to apply commands. It works both with anonymous commands and with regular commands.

to test
  
  let worldsize [0 5 0 5]
  apply-command "resize-world" worldsize
  
end



to apply-command [command inputlist]
  ; Takes two inputs
  ; 1: Anonymous command/string containing anonymous command/string containing regular command
  ; 2: A list of inputs, corresponding in length to the number of inputs the command takes
  ; Applies the command with the different items of the list as input
  ; Heavily inspired by stackoverflow-user Bryan head
  
  set command anonimify-command command length inputlist ; Using non-anonymous commands gave issues, hence they are anonimified
  (run listify-command command length inputlist inputlist)
  
end

to-report listify-command [ command num-args ]
  ; Takes an anonymous command and the length of a list as input
  ; Outputs an anonymous command that takes the different items of the list as inputs
  ; Heavily inspired by stackoverflow-user Bryan head
  
  if (not is-anonymous-command? command) [error "The first input for listify-command has to be an anonymous command"]
  
  let args (reduce word n-values num-args [ x -> (word " item " x " ?") ]) 
  ;show (word runresult (word "[ ? -> (run command " args ") ]"))
  report runresult (word "[ ? -> (run command " args ") ]")
  
end

to-report anonimify-command [ command number-of-inputs]
  ; Takes two inputs
  ; 1: Takes an anonymous command, a string containing an anonymous command or a string containing a regular command
  ; 2: Takes a number that corresponds to the number of inputs the anonimified command should take
  ; Returns anonymous commands unaltered
  ; Returns strings containing an anonymous command as an anonymous command
  ; Returns strings containing a regular command as an anonymous command
  
  if (is-anonymous-command? command) [ ; Anonymous commands get returned
    report command
  ] 
  
  if (is-string? command) [ ; Strings are processed
    carefully [ ; Using run-result on a string that does not contain an anonymous command causes an error, hence carefully
      if (is-anonymous-command? run-result command) [ 
        set command run-result command
      ]
    ]
    [
      let inputs n-values number-of-inputs [ i -> word " x" i]
      let inputs-as-string reduce word inputs
      let command-string (word "[ [" inputs-as-string " ] -> " command inputs-as-string" ]")
      set command run-result command-string
    ] 
    report command
  ]
  
  error "The inputted command must be either an anonymous command, a string containing an anonymous command or a string containing a command"
  ;If the input is neither anonymous command nor string, an error is displayed
  
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top