Skip to content

Instantly share code, notes, and snippets.

@sogaiu
Last active April 4, 2025 13:04
Show Gist options
  • Save sogaiu/1ea1fffe2cc713ef8b1947827de58413 to your computer and use it in GitHub Desktop.
Save sogaiu/1ea1fffe2cc713ef8b1947827de58413 to your computer and use it in GitHub Desktop.
racket notes

unexpected bits

  • "printing" (default) is different

    • e.g. what should '(1 2 3) "print" at the repl? in clojure, janet, etc. one would typically get (1 2 3), but in racket, the default is '(1 2 3) (though it's configurable))

    • [racket] Quoted expressions in #lang racket

      $ janet
      Janet 1.37.1-06d581dd linux/x64/gcc - '(doc)' for help
      repl:1:> (def result (eval (parse "'(1 2 3)")))
      (1 2 3)
      repl:2:> (type result)
      :tuple
      repl:3:> (length result)
      3
      repl:4:> result
      (1 2 3)
      
      $ clj
      Clojure 1.12.0
      user=> (def result (eval (read-string "'(1 2 3)")))
      #'user/result
      user=> (type result)
      clojure.lang.PersistentList
      user=> (count result)
      3
      user=> result
      (1 2 3)
      
      $ racket
      Welcome to Racket v8.15 [cs].
      > (define result (eval (read (open-input-string "'(1 2 3)"))))
      > (list? result)
      #t
      > (length result)
      3
      > result
      '(1 2 3)
      
    • Output Printing Styles

  • running a .rkt file that is:

    #lang racket
    
    1

    will print out 1 (without explicitly requesting printing with display or similar...)

    • https://stackoverflow.com/questions/41063011/how-to-get-racket-to-not-print

      #lang racket, the default language in the Racket implementation, prints top level statements except (void), that returns a value that is always ignored by the REPL, and (values), which return zero values back and thus REPL has nothing to print. This means you can make a main function that ends with either one of them and it will have no output from the REPL.

  • "expressions" don't include things like (define (f x) ...), i.e what "expression" refers to seems "narrower" than in other (non-scheme) lispy languages.

    • e.g. (define (y x) (* x x)) is not an expression in racket apparently, even though (+ 1 1) is.

    apparently "definitions" are their own thing, kind of "on par" with "expressions".

    there might be a good reason for this, but haven't determined it yet. looking at r4rs:

    A Scheme expression is a construct that returns a value, such as a variable reference, literal, procedure call, or conditional.

    via: https://people.csail.mit.edu/jaffer/r4rs_6.html#SEC24

    since (define (f x) ...) doesn't return a value in racket (or scheme?), may be that makes it "not an expression"...

    Definitions are valid in some, but not all, contexts where expressions are allowed.

    via: https://people.csail.mit.edu/jaffer/r4rs_7.html#SEC41

questions

  • how to find the source code for any given bit of racket?

  • what is a value?

    In particular, a value, such as the number 2, is an expression that evaluation simplifies no further.

  • what is an expression?

    An expression can be a literal constant that is a number (type Number), a string (type String), a symbol (type Symbol) written with quote or ', an S-expression (type S-Exp) written with quasiquote or `, #t (type Boolean), #f (type Boolean), or a character (type Char). An expression also can be a bound identifier (in which case its type comes from its binding).

  • what is an identifier?

    An identifier is a source-program entity. Parsing (i.e., expanding) a Racket program reveals that some identifiers correspond to variables, some refer to syntactic forms (such as lambda, which is the syntactic form for functions), some refer to transformers for macro expansion, and some are quoted to produce symbols or syntax objects. An identifier binds another (i.e., it is a binding) when the former is parsed as a variable or syntactic form and the latter is parsed as a reference to the former; the latter is bound.

    1.3.3 Identifiers

    An identifier is a sequence of one or more non-delimiter characters. Identifiers are used in several ways in Scheme programs:

    • An identifier can be used as a variable or as a syntactic keyword.
    • When an identifier appears as a literal or within a literal, it denotes a symbol.

    The R6RS Scheme report, in 4.2 Lexical Syntax, uses the term identifer to refer to the character-level syntax. That is to say, roughly, identifier means something like the lexical token from which a symbol is constructed when the expression becomes an object. However, elsewhere in the text, identifier seems to be freely used as a synonym for symbol. E.g. "Scheme allows identifiers to stand for locations containing values. These identifiers are called variables." (1.3 Variables and Binding). Basically, the spec seems to be loose with regard to this terminology. Depending on context, an identifier is either the same thing as a symbol (an object), or else : the grammar category from the lexical syntax.

    "Identifiers" are a syntactic category. That is, suppose we take a text file and break it up into tokens. Some of those tokens will be left-parens. Some will be right-parens. Some will be numbers. Some will be identifiers. Every language has its own set of syntactic categories, but many of them use the name "identifier" for "word-like thing that can usually be a function name or a variable name or whatever."

    "Symbols", on the other hand, are a particular kind of value in Scheme and Lisp systems. Scheme has lots of different kinds of values: Numbers, Booleans, Strings, Pairs, Symbols, and others.

    In Scheme, when developing a parser/interpreter/compiler/whatever, it turns out to be very convenient to use symbols (the values) to represent identifiers (the syntactic entities). Specifically, "quote" has a special ability to turn certain host language token sequences into lists of symbols, numbers, strings, and booleans. You don't need to take advantage of this, but it eliminates a lot of code.

  • what is a "source-program entity"? - no answers so far

    • any relationship to "external representation"?

      1.2.6 External Representations

      An important concept in Scheme is that of the external representation of an object as a sequence of characters. For example, an external representation of the integer 28 is the sequence of characters ‘28’, and an external representation of a list consisting of the integers 8 and 13 is the sequence of characters ‘(8 13)’.

      The external representation of an object is not necessarily unique. The integer 28 also has representations ‘#e28.000’ and ‘#x1c’, and the list in the previous paragraph also has the representations ‘( 08 13 )’ and ‘(8 . (13 . ( )))’.

      Many objects have standard external representations, but some, such as procedures and circular data structures, do not have standard representations (although particular implementations may define representations for them).

      An external representation may be written in a program to obtain the corresponding object (see Quoting).

      External representations can also be used for input and output. The procedure read parses external representations, and the procedure write generates them. Together, they provide an elegant and powerful input/output facility.

  • what is a symbol?

    A symbol is an atomic value that prints like an identifier preceded with '. An expression that starts with ' and continues with an identifier produces a symbol value.

    A symbol is like an immutable string, but symbols are normally interned, so that two symbols with the same character content are normally eq?. All symbols produced by the default reader (see Reading Symbols) are interned.

  • how are symbols and identifiers related?

    A value that prints like a quoted identifier is a symbol. In the same way that parenthesized output should not be confused with expressions, a printed symbol should not be confused with an identifier. In particular, the symbol (quote map) has nothing to do with the map identifier or the predefined function that is bound to map, except that the symbol and the identifier happen to be made up of the same letters.

  • what is a variable?

    A variable is a placeholder for a value, and expressions in an initial program refer to variables. A top-level variable is both a variable and a location. Any other variable is always replaced by a location at run-time; thus, evaluation of expressions involves only locations. A single local variable (i.e., a non-top-level, non-module-level variable), such as an argument variable, can correspond to different locations during different applications.

editor stuff

reference notes

this:

  • values are the results of expressions
  • objects actually hold data

but also:

however, a value [can also be]is a reference to an object stored somewhere else.

via: https://docs.racket-lang.org/reference/eval-model.html#(part._.Objects_and_.Imperative_.Update)

misc

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment