Conventional Functions

not perfect by any means but;

Screen Shot 2022-05-13 at 9.53.08 AM

recursion

untitled script pic(15)

function passing

untitled script pic(19)

object manipulation

untitled script pic(20)

some dynamic scoping

untitled script pic(16)

kind of...

untitled script pic(17)

continuations (with return block)

untitled script pic(21)

lambdas

untitled script pic(22)

heres the project link. the implimentation is kind of weird, but it doesnt require js! although there is a script that sets things up more properly (still dont know any other way to default to 0 mulit-arg inputs...). just be careful if you go to edit the blocks, this untitled script pic(23) is actually a command ring (yes, untitled script pic(24)) that is very unhappy about its current condition. i wouldnt touch it.

For some of it, couldn't you just do something like
untitled script pic (48)
?

(Correct me if I'm wrong, but this just seems a lot simpler with retaining a lot of the functionality.)

This is quite interesting. I don't have time right now to look inside it, but I will this evening. Am I seeing variadic upvars? The part you labelled "continuations" looks to me like just BREAK, although maybe that's just the example.

yes but I am a sucker for syntax and I really like the idea of functions with c-slots. it's nothing you couldn't do before but I do think it would be nice to have more flexibility when it comes to writing functions. and I find the func ( arg1, arg2 ...) easier to read and understand than call (ring/var) with inputs (args...) especially when you plan on passing functions as arguments. also the drop-down menu vs dragging / dropping variables

One more thing: do these blocks have help menus? I think that this function library would be a super cool tool, but I also know that I am super forgetful and it is not the best for me to be constantly visiting back just because I don't know what one input slot is for.

Yes, that's what mostly makes it interesting to me. I'd love to be able to put a procedure in a variable and then have it appear as a block with inputs rather than just as a variable. But that would be super hard to implement, and your menu of them strikes me as a good compromise. And it seems also to solve the problem of internal definitions (make a block inside another block).

I was actually trying to do something just like that last night. I extended the template slot morph input to accept type / category / and spec arguments and actually got a command block template to take place of the reporter block. it was really neat (albeit, unusable). you'd still have to attach a definition to it, which wouldn't be so much trouble if there was an intuitive, user friendly way to define the inputs and block spec in general.

and as to this project, I had to do a lot of 'dirty' tricks to get this as functional (pun intended) as it is. the variadic upvars are just that, actually they're template slots, %mult%t, initially I had them as blockVars but I had to get rid of that label. the c slots aren't the ones you select in the user interface either, they're %cl, and I pass both those arguments into a command ring, which the c slot takes place of the actual slot itself (so there's a variable reporter in the command slot), otherwise it won't evaluate into the command itself, and the parameters are passed in as a list of inputs to the ring parameters (which is also, unachievable normally) that's the whole deal with the ring I was talking about toward the end of the post.

there's got to be a better way but that's just how I ended up getting it to work. rings don't take inputs very well, (like via the join method) not that I can find.

it's pretty straight forward, it mimics the same syntax as javascript and similar languages where you define a function like this

function add(a, b) {
    return a + b;
}

and to call it

add(5, 6);

most of those blocks are just different forms of those two actions for different situations in snap.

also, it's notable that functions don't require a name, you can assign a variable to an anonymous function (just like lambdas / grey rings in snap) and pass those around as arguments.

I'll explain a little better when I get home from work.

Really, given our roots, you should use the Lisp notation (add 5 6). It's a little counterintuitive for people used to $$f(x)$$ in math, but it makes the entire procedure call a list that can be manipulated like any other list, used as input to a procedure, etc.

But since the whole thing is a block, and manipulable that way, I guess the notation isn't so important.

I personally like javascript syntax better since it makes it less confusing.

I am really taking the project not so much as a thing in itself, since you suggest that it's fragile, but rather as a proposal for a notation we might implement. Some pieces of it are entirely cosmetic (RETURN instead of REPORT), but the various FUNCTION blocks are pretty nice. (I don't find the => versions so compelling; those are simply equivalent to gray rings.)

There are a lot of details I don't fully understand yet because I've been in meetings and haven't been able to play with the code. For example, what's the scope of definitions made with the named FUNCTION blocks inside the code of a custom block?

Also, when I run that one-line script when the project opens:

that's one thing I don't really understand about lisp / that way of thinking, does it not make more sense to have the function be something seperate from the inputs? I mean I can say add (5, 88, -2) or I could say add (-2, 88, 5) and they both make sense and I can add remove rearrange, whatever it's still add these. but (add a b c) makes no sense as (c b a add) or any way without add at the front (does it?) to me im adding a list of items, not doing the first item of a list to the rest of the list

or at least I would think if you wanted to take that procedure / function as a whole it would be (add (a b c)) what's the big prize for shifting your entire way of thinking? even just infix notation -> prefix notilation is a pretty mighty jump, does it really provide that much more flexibility?

on my way home now from work, when I get back I'll get into the project and address some of those things. it's kind of in an in between state as I'm still working on it so mind the bugs and sloppy code :stuck_out_tongue:

What it provides is not flexibilty so much as uniformity. You think $$f(x)$$ covers all function calling, but that's because you're taught not to regard +, −, ×, ÷, <, =, !, √ and so on as not being functions but rather in some special category ("operators" for example). APL solves the uniformity problem by limiting itself to functions of at most two arguments, using prefix for monadic ones (!5, not 5!) and infix for dyadic ones. Lisp's solution is more general; functions can take any number of inputs and are always prefix.

Actually, in the very early days of Lisp, when it was still just a specification of a language and not yet implemented, there were two different notations. The one we all know and love, "S-expressions," S for Symbolic, was for use inside procedure definitions. For toplevel expressions, you'd use "M-expressions," for Meta I think, in which there was always a function call (maybe niladic), the function name came first, outside the parentheses (which were actually square brackets in M-expressions) as you prefer, and the argument subexpressions weren't evaluated, so you could use a list as input to a function without quoting it. But it turned out that S-expressions are trivial to implement, and users preferred using them over trying to keep two different notations straight in their heads. The big syntactic contribution of Scheme is that it's a Lisp-1, meaning that function names are in the same namespace as all other names, so the way the function name is evaluated is the same as evaluating any other name, namely variable lookup.

The trouble with (add (a b c)) is that it's confusing if A is a procedure. Do you mean to call it, or is ADD a higher order function? The Lisp notation emphasizes that procedure expressions are evaluated, same as argument expressions. Consider ((lambda (x) (x a b c)) add).

By the way, I wish you wouldn't fetishize Javascript by continuing their totally wrong meaning for the word FUNCTION. Command blocks aren't functions. (Technically, neither is RANDOM, but I wouldn't insist on that level of sophistication.)

You're cheating by using a commutative, associative function as your example. (sub a b) wouldn't mean the same as (sub b a).

What do you mean? As a person who grew up on JS I don't know what to make of that.

tone things because i dont want this to be read wrong

I'm seriously asking about what you mean, and half-joking about not knowing what to make of it. I think I know what you mean, but only a little.

In mathematics, a function is an association where every x value gives zero or one y values. JS uses it to mean any whatchamacallit.

Ohh, that makes sense. I knew about mathematical functions being different, but I didn't know to what degree. Thanks!

still learning about continuations, actually have the reference manual open behind this window from earlier (page 90 lol), anyways:

there is actually a difference, the reason i dont just use report is because i want the functionprocedure(??) to return to where it was called in the script, not report a value. in some cases they are interchangeable and thats what i was doing at first but i ran into problems testing out different cases, like this example

ex

untitled script pic(25)

is supposed to show the stack like behavior in recursion. the function call remembers its spot in the script so it can continue where it left of if told by a return block (and pass a value, if specified, to wherever its at.) the report block has undesirable behavior:

ex

untitled script pic(26)

got me there. so is this:

ex

untitled script pic(27)

except your parameters are at the top / beginning-before the script that uses them, instead of off somewhere to the right middle / bottom end.

no clue, havent messed with that dynamic yet, im still try to get local scopes (nested functions, closures) to work correctly. ive already got two different variable getters / setters:

ex

untitled script pic(32) : untitled script pic(30)
untitled script pic(33) : untitled script pic(31)
defined like
untitled script pic(29)
untitled script pic(28)
because they behave differently depending on the context ie. this:

untitled script pic(34)

doesnt work, but

untitled script pic(35)

really it seams i need to use extension versions (the let blocks) if i want any kind of nesting

untitled script pic(36)untitled script pic(38)

but closures wont work either way. i think i have to have explicitly declare parameters before passing them to the ring within the function blocks and hopefully as ring parameters they can still count as a reference to that declaration and be used similarly as those let vars in that example

...

well, speaking of

ex

untitled script pic(40)
untitled script pic(39)

so thats kind of nested scoping but this is already quite a long reply so im going to go keep working on this, but one more thing

function procedure, tomato tomato. 'to me they are the same because i dont know the difference.' (im quoting myself, can you do that in lisp? :​P)

please, give me your own definition of procedure so i know what you mean. and then if you dont mind, the discrepancies between that and a function. for once and for all (mwhaahahaha) (feels like an evil laugh moment idk)

A function is a relationship between some number of input values and an output value, such that when the function is applied repeatedly to the same input, you always get the same output. Thus, RANDOM is technically not a function, because it can be called twice with the same inputs and get different outputs.

This is a mathematical definition, not an operational one. There's no requirement that a function be computable; in fact, almost all functions are not computable, because the number of possible computer programs is countably infinite (you can number them), whereas the number of possible functions is uncountable. (If you try to number them, even with an infinite number of integers, there will still be functions left uncounted.)

(In fact, almost all functions can't even be described, because there are only countably many strings of characters. This is strange stuff. But don't despair; all the functions that anyone cares about can be described, by explaining why they're interesting.)

The function is the association between inputs and outputs, regardless of how computed. For example, $$f(x)=2(x+3)$$ and $$g(x)=2x+6$$ are the same function, even though they're different algorithms and, if implemented as described, different computer programs. In technical terms, a function is a set of pairs (input value, output value). The set is usually, but not always, infinitely large. (The Boolean operators such as AND are finite sets of pairs.)

You know what a procedure is. Technically, computer programs are always made of procedures, not functions, because the program describes an algorithm, not an abstract association of inputs with outputs. But we computer people generally abuse the language by using the name "function" for a procedure that computes a function. A procedure that, instead, has an effect without returning a value doesn't represent a function, let alone being one.

(To be sure, many computer people, including all Javascript programmers, are willing to use the name "function" to label any procedure. But I think that usage makes it harder to talk about the difference between, in Snap! terms, jigsaw-puzzle-piece shaped blocks and oval or hexagonal blocks. The reporters (including predicates) can be used in composition of functions $$f(g(x))$$. Commands, by contrast, are used only in sequences, which are less interesting theoretically.)