Skip to content

7ML7W Factor Day 2 Painting the Fence

Paul Mucur edited this page Mar 17, 2018 · 2 revisions

Muffled introductions take place, muffled due to the presence of extremely tasty bread being extremely thoroughly consumed. Thanks Charlie!

What do we want to talk about?

We conclude we want to do the exercises together mainly, with James A's expert REPLing

Symbols - these are new and vaguely variable-esque. What do we think about these?

Tom: I didn't see the point of the stack effect stuff. What do the input and output names get used for?

James A: I think it said "they don't matter"

Mudge: These come into the exercises, but aren't really explained in the chapter. Let's find out!

The chapter then

We finally get to files, and tests, and other programmingy things.

Defining words

These takes the form

: word-name stack-effect implementation ;

Tom: Why do these things need to declare arity, when quotations don't? Quotations are pretty much anonymous functions, so what's the deal?

Our example is adding 42 to the nearest value on the stack

IN: scratchpad : add-42 ( x -- y ) 42 + ;
IN: scratchpad 123 add-42 .
165

You seem to be able to use anything as identifiers in the stack effect:

IN: scratchpad : add-43 ( 1 -- 2 ) 43 + ;
IN: scratchpad 123 add-43
166

But it is checking arity:

IN: scratchpad : add-44 ( x y -- z ) 44 + ;
:errors - show 1 compiler errors
IN: scratchpad :errors

==== <Listener input>

<Listener input>

Asset: add-44

Stack effect declaration is wrong
inferred ( x -- x )
declared ( x y -- z )
:errors - show 1 compiler errors

James A: in the GUI app at least you can define a word and its documentation from the stack effect is dynamically added to the system's live docs, which is nice

Returning multiple values

You can easily say "this will put two things on the stack:

: push-1-2 ( -- x y ) 1 2 ;
push-1-2

--- Data stack:
1
2

Help

Appropriately enough I lost the thread here. Something about backslashes and sequences and accessing docs. We have no idea what we're doing and generate a bunch of weird errors by trying to get help for the word that matches the last identifier on the stack? I think?

Vocabularies then

Akin to namespaces - e.g. in our repl we always see IN: scratchpad, cos we're defining stuff in the scratchpad namespace vocabulary.

We learn about "restarts" via the helpful messages you get when you don't have the right vocabulary loaded:

1: number>string
                ^
No word named “number>string” found in current vocabulary search path

The following restarts are available:

:1      Use the math.parser vocabulary
:2      Defer word in current vocabulary

Type :help for debugging help.
IN: scratchpad :1
1: Note:
Added "math.parser" vocabulary to search path
Data stack underflow

Symbols

Leo: They seem like globals, right?

Yeah, a bit.

Tom: I was really surprised by this - all this faffing around with the stack and you can just, like, stuff things into globals?

James C: are these just a convenience, or computationally essential to reach turing completeness?

Tom: I'd assume that because one of the things you can push on the stack is arbitrary code, that should be enough. There's not much motivation for them in the book, so I would guess they're a convenience?

Mark: I was kinda disappointed by this to be honest.

Mumbles of "boo, sellout" (aimed at factor, not Mark, to be clear)

Tom: It's probably pragmatism, isn't it.

[mumbled suggestions that we like our side project languages ideologically pure]

Tom: you could think about this a bit like a stack-based CPU, where the CPU is still working with stacks, and still have system memory somewhere that your stack instructions can access?

James C: in hard real-time systems you tend not to have, say, garbage collection, because it can introduce unpredictable pauses. So maybe there's a case here to say it's good to have some sort of statically declared global state that's fixed? But OTOH these names can refer to arbitrary and changeable values, so you'd still have the GC problem. Hmm.

Standalone programs

Some $FACTOR_ROOTS discussion. Is it like $GOPATH or is it more like the java classpath? It's probably more like the latter, particularly given factor's JVM heritage. James A has already set his up.

Mudge: so there's lots of examples, and they're all intentionally broken, hurrah.

We tackle writing a greeter vocabulary - despite our $FACTOR_ROOTS we get an error referring to swap, because in standalone files we don't get everything loaded for us by default, just a massive unhelpful stacktrace. So we need our program to be:

USING: kernel sequences ;
IN: examples.greeter

: greeting ( name -- greeting ) "Hello, " swap append ;
USING: examples.greeter io ;
IN examples.hello

: hello ( -- ) "world" greeting print ;
$ factor examples/hello.factor
Hello, world

Dmitry: can we use fully-qualified names without inputs?

We don't know.

A bit of chat about whether it's good to have pedantically enumerated explicit imports vs a bunch of things conveniently available or not, and as you can imagine we arrived at a single, conclusive answer, which was that [unintelligible].

Testing then

You have to be hella precise with your naming or it just gets ignored here. Conventions eh!

Tom: A convention with which you MUST comply

We run a test and see some glorious output, in particular some glorious failures.

[At this point we read through the test runner example line-by-line]

HMM not sure:

So the interesting thing here seems to be that this runner seems to stick its results in a symbol which you can access later (c.f. compiler :errors. And indeed we've got some convenience word :test-failures which isn't the symbol called the same thing, but instead pretty-prints your failures.

Simon: is with-null-writer also using symbols to define what the IO streams are?

Mudge: Maybe? It's definitely using some sort of global state for streams. I think we see this later.

Tom: I think it might be a bit rubyish - you've got constants STDOUT and STDERR and then mutable globals $stdout and $stderr, which lets you temporarily reassign things and put them back after.

Interview with Slava Pestov

Q: Why?

A: Fun.

He mentions [ being a word, which knowledge we combine with our newfound docs expertise:

IN: scratchpad \ [ help
[
Factor documentation > Factor handbook > The language > Syntax > Literals > Quotation syntax
Next: ] ( -- * )

Vocabulary
syntax

Syntax
[ elements... ]

Word description
Marks the beginning of a literal quotation.

Examples
[ 1 2 3 ]

See also
]

Definition
USING: parser sequences ;
IN: syntax
SYNTAX: [ parse-quotation suffix! ;

That's a pretty cool stack effect too - * for variadic output?

James A: Hey, look at that SYNTAX: declaration. I bet we can do one of those!

[James proves this by defining syntax % that prints the word "wibble"? I think?]

Some random chat about producing native executables

We agree that this is good. Is it portable though?

We could run deploy-tool, if only we could find it. Is it an executable? A word? A fish? A loaf? WHO KNOWS.

Googling doesn't help. Is this a totally ungooglable language?

James A: So much R stuff comes up. Which is ironic, as R is itself totally ungooglable.

[We work it out - you do it at the repl probably, or in your own build program. I miss the correct incantation.]

[10 minutes pass]

[It turns out the compile failed and we've uncovered a bug in factor? Maybe? As long as it fails on multiple CPU architectures it's still portable, though, which is the main thing.]

Exercises

We run into LOTS of trouble trying to implement the find-first exercise using find. But we get a super-weird operator about inline words out of this, and looking at the docs for find we see that it's a macro?

Mudge: so I think this is kinda what we're seeing here is that the find macro is using its stack effects to try to check that the arguments you're providing it match what it expects. We can short-circuit this with inline but that's really like cheating.

James C: is this really the point of this exercise, or is there actually a way to write a loop over a sequence in factor?

We're not sure.

Tom: can we also make this pass by using the right incantations in the stack effect for our own find-first word? I.e. by replicating the nested stack effects of the find macro?

[we try this, and no, same error]

Mudge: Okay but we can by doing [unintelligible]

[Something happened here. It involved curry, nested quotations, call( and quite possibly magical beans.]

James C: This is unreasonable. find is a really simple combinator.

Joel: I fixed this with inline, but I didn't really understand what inline does so I put it first, and it just worked.

[we verify that it totally does]

It seems like none of us know what inline does and we don't know where we would've been expected to find this out. Bleh.

Mark: It declares the most recently-defined word as an inline word.

All: OKAY so that's why it didn't matter where it goes.

After ~10 minutes of mobbing the solution to numberguess an actual angry mob turns up and we are forced at pitchfork-point to convene a swift...

Mudgerospective

Charlie volunteers to organise the next meeting! Thanks Charlie.

At this we run off because we've run over. Some delayed retrospective action's going on in the book channel on slack, which might get transcribed here later.

Clone this wiki locally