Additional libraries

I’m building a library of generally useful functions, complementary to Snap!’s official (and may I say: excellent) libraries. This work-in-progress is published and irregularly updated in the “Programming tools” project; each sub-(ject) library is linked to one of the sprites. I’m looking forward to extension, improvement and collaboration suggestions.

Link: Snap! Build Your Own Blocks

This is an interesting collection! Of course I smiled at "accumulate (SICP)."

LOOP ... HOLE ... cute pun.

Canonical DEEP REVERSE:

NEW SCANNER is a great thing to have in a library. I might add it to List Utilities, except that I don't like the name "scanner." It should really be "iterator," but that might be too many syllables for Snap!. I'd call it "stepper" except that we already have something called "stepping." Hmm, to be considered further... Actually, thinking it over more, reporting a procedure to be assigned to a variable is elegant in itself, but invoking such a procedure in Snap! isn't so elegant, so I'd be inclined to metaprogram this: if the input is a variable, define a procedure NEXT FOO where FOO is the variable name, and then have a global procedure NEXT that takes a variable as input and invokes the right NEXT-FOO. I'm not sure; it wouldn't work to have two different iterated variables with the same name in different scopes, etc. Oh, a little quibble: "getting a" in the error message should just be "getting."

Interesting but unimportant linguistic remark: What you call rotating down I would call rotating up. :~)

There's a bug in the recursive version of ITERATE: The variable that's called BODY in the header is called ACTION in the body. Btw, you noted that it uses recursion; what I find noteworthy is that the recursive call is a tail call, so it generates an iterative process.

Your extensible LET is very clever! It applies the CASES move to SET, so to speak. I was going to say "it's not LET but rather LET✽, the variant version that does the value computations in sequence, rather than in parallel," but luckily I decided to make sure I was right before posting this. And I'm not; this is indeed LET. Which means that I don't understand how Snap! expressions are evaluated. :~(

MULTIVAR-MEMOIZE is great! Don't you love how you can abstract over functions? I'm wondering if you could simplify the code by using MEMOIZE as a helper. So the nonterminal values in the memory would be functions rather than memories.

Well,I made it a long time before and it was anthropromorphically called gobbler


(this pic is just for block importing,the apl here doesn't mean the apl you hope it means,it does not have function library stuffs)

Yeah, that errs in the opposite direction from "iterator": too informal. "Extractor"? "Item getter"?

istream?

Well motivated, but I don't know what the "I" stands for, so users won't know either.

Maybe we should stop hijacking this thread.

Thanks for the compliment!

Agreed, the canonical version is probably superior to what I thought up. For one thing, the code looks less complicated, which ceteris paribus is usually a good thing. I’m going to compare performance, and unless my version is much faster I’ll replace it. [UPDATE; the “canonical” version is also much faster, I’ll use it from now on]

“reader”? “nibbler”? “digester”? “bite off”?

I don’t get your point. The application is actually quite similar to the “counter” example (not: “counter example” :wink: ) in Ch. VIII, section A, from Snap!’s Ref. Manual. Metaprogramming on the other hand I consider a nuclear weapon :comet:, only to be used when necessary.

As a matter of fact I was inspired by the Hewlett-Packard RPN calculators’ R↓ and (later) R↑ functions. HP’s registers are dubbed X, Y, Z, and T(op); the equivalent item numbers would be 1, 2, 3, 4. R↓ (“roll down”) will move data from e.g. Y to X, which in my projection is like moving data from item 2 to item 1. Perhaps I’ll rename the function R↓ anyway, honoring its origins.

Thx; fixed it.

Better ask @jens :slight_smile:

What I like most about memoizing in general is how it instantly makes practical an elegant theoretical concept (recursion) which also often makes easily understandable code.

I ‘ve been looking into that already, but didn’t (yet) find a working and efficient solution. My gut feeling says it probably exists. I’ll keep trying.

Ah. Yeah, it was weird when HP did it too. The metaphor about stacks comes from the stack of plates at serve-yourself cafeterias, where you grab the top plate, and when they bring a pile of clean dishes from the kitchen they put them on top of the stack.
plate-stack
The stacks are springloaded so that you can always reach a plate even when there aren't very many.

Yeah, I know. I don't like it there either. One of the ways I keep annoying Jens is by suggesting that when you put a procedure in a variable, the orange oval in Variables should change shape into whichever kind of procedure it is (command, reporter, predicate) and have enough input slots to match the arity of the procedure. Then you could use it without needing RUN or CALL. (He says, reasonably enough, that everything would break when you change the value of a variable from a procedure to a non-procedure, because there would already be calls to the procedure-valued variable in your code.)

I worked it out; it’s slightly slower but hardly noticeable:

Actually the original MEMOIZE (for recursive functions with 1 input parameter) won’t be needed anymore. This function will work both with a list of parameters as input and with a single (non-list) parameter; it will convert the latter to a one-item list for internal use.

This is a little complicated; the user might have a single input that's a list, and then you'll try to use it as an input list.

True. However this wouldn’t be any different without the conditional value-to-list conversion (even so, I’m probably removing the value-to-list conversion anyway, in order to simplify the code).

In my view it would be preferable if variadic input could be used with a function assigned to a variable; thus within the following block:

… calling the memoizer (e.g. option A) would be like:

instead of:
. I have understood this to be impossible, is that correct?

I'm not sure I understand you fully. You can certainly do what's in your example. The thing you can't do straightforwardly is use a variadic input (i.e., a list containing all the individual input values the user provided) as input to a recursive call to the same procedure, because the list isn't whatever kind of data the procedure expects in the individual variadic inputs. Instead you have to use INPUT LIST: for the recursive call. See pp. 68-69 of the manual.

I’m aware of what’s on pp.68-69 of the Ref. Manual. What I meant to say is I believe there is no way of calling a function that was assigned to a variable using a grey ring, using “INPUT LIST:”. E.g if I were to move a variable or reporter block over the arrows that are at the grey ring itself, nothing happens; neither can I declare one of the inputs as variadic. The only way I know of to have such a (lambda) function process variadic input is to treat one of the inputs declared at the grey ring as an input list, which is what I do in the case of multi-memoize. But I’d prefer to have it the other (more usual) way.

Oh. I did say "I'm not sure I understand you fully"! ;~/ I'll look into this when I get around to it. :tuit: