Core Expression Language Revision 1 March 25, 1998 Proprietary Rights Notice All rights reserved by Mulberry Technologies, Inc. No part of this material may be reproduced, translated, or transmitted in any form or by any means, electronic, mechanical, or otherwise, including photocopying and recording, without the permission in writing from Mulberry Technologies, Inc. Disclaimer Mulberry Technologies, Inc. makes no representation or warranty, express or implied with respect to this publication or the programs or information described in this publication. In no event shall Mulberry Technologies, Inc., its employees, or contractors be liable for specific, indirect, or consequential damage. © 1997, 1998 Mulberry Technologies, Inc. All rights reserved. Introduction DSSSL's expression language is defined in Section 8, Expression Language, of the Standard. As the minimum necessary to support if not life then stylesheets, Section 8.6 defines a subset of the expression language as the “Core Expression Language”. This discussion presents the elements of the Core Expression Language in a different order to that of the standard. The discussion begins by defining the different types of objects in the Core Expression Language. Included with the discussion of each object type is the description of the object's type predicate procedure – a procedure that returns a true value only if its argument is of the matching type or possesses the quality being tested. The advantages of this discussion over that in the standard are that more examples are presented and that the discussion occasionally strays into observations about how to use the objects or how they are implemented in Jade. Following the discussion of the types is a listing, with numerous examples, of the remaining syntax expressions and procedures defined in the Core Expression Language. Again, the order differs from that of the standard: variable definition and the test for equivalence are presented first, then the procedures for quantity, list, character, string, and procedure objects (plus some procedures not related to Core Expression Language object types) are described and numerous examples are given, before the logical operators and the if, cond, and case expressions are presented. The discussion ends with a copy of the Core Expression Language syntax productions and procedure prototypes and, of course, an exercise. Format of Procedure or Expression Definition An example of a procedure or expression definition is shown below. The title of the definition is usually the same as that in the DSSSL standard, and the corresponding section number from the standard is in square brackets follows the title. Following the title is the prototype or prototypes of the procedures or expressions being defined and a discussion of the operation of the procedures or expressions plus examples of the procedures or expressions. The left hand side of each example (before the “⇒”) is one or more expressions, and the right hand side of the example is the result of evaluating the expression on the left hand side. In the three examples above, one expression returned #t, and the other two returned #f. About This Tutorial This tutorial is derived from tutorial material produced for use at Mulberry Technologies, Inc. and is made available to the DSSSL Documentation Project by Mulberry Technologies, Inc. Object Types Numerical Types [8.5.7.1] DSSSL provides a quantity data type that represents lengths and quantities, such as areas and volumes, that derive from lengths. Lengths have dimension 1; areas, 2; and plain old numbers, dimension 0, making them dimensionless. The base unit for lengths is the meter, with symbol m. Syntax of Numerical Constants [8.5.7.4] A quantity may be written in binary, octal, decimal, or hexadecimal by the use of a radix prefix: Radix Base #b Binary (base 2) #o Octal (base 8) #d Decimal (base 10) #x Hexadecimal (base 10) If no radix, a quantity is assumed to be decimal. A decimal number may have a decimal exponent; for example, 1e0. A numerical constant may have a unit suffix, possibly with a multiplier raising (or lowering) the power of the quantity associated with the unit; for example, 1m, 1.0m, 1m2, 1m+2, or 1m-2. Number Type Predicates [8.5.7.5] (quantity? obj) (number? obj) (real? obj) (integer? obj) These return #t if obj is of the named type, otherwise they return #f. The predicates are listed in order of decreasing abstractness. In general, if a predicate is true for a given obj, then the more abstract predicates also evaluate to #t. (quantity? 1m) ⇒ #t (number? 1m) ⇒ #f (real? 1m) ⇒ #f (integer? 1m) ⇒ #f (quantity? 1.2) ⇒ #t (number? 1.2) ⇒ #t (real? 1.2) ⇒ #t (integer? 1.2) ⇒ #f (quantity? 9) ⇒ #t (number? 9) ⇒ #t (real? 9) ⇒ #t (integer? 9) ⇒ #t Length Lengths are explicitly covered in the core expression language, but a length is a quantity of dimension 1. There is no type predicate for length defined in the standard. Exact and Inexact Numbers [8.5.7.2] DSSSL, and Scheme before it, distinguishes between quantities that can or should be represented exactly and those that may not. For example, an index into a data structure should be known exactly; an index would be “4”, not “4.0”, “4.00001”, or “4e0”. A numeric constant is inexact if it contains a decimal point, an exponent, or a unit. The exactness or inexactness of a quantity is independent of its dimension. In general, rational operators such as + return exact results when given exact arguments, and, with the exception of inexact->exact, the procedures defined in the standard return inexact results when given inexact arguments. Inexactness is contagious; a quantity will be inexact if it is declared as an inexact value, if it is derived from expressions returning inexact values, or it is derived from inexact arguments. Exactness Predicates [8.5.7.5] (exact? q) (inexact? q) exact? returns #t if q is an exact quantity, otherwise returns #f. inexact? returns #t is q is an inexact quantity, otherwise returns #f. For any quantity, only one of these predicates will return #t. (exact? 4) ⇒ #t (exact? 4.0) ⇒ #f (exact? 4.00001) ⇒ #f (exact? 4e0) ⇒ #f (exact? 4m) ⇒ #f (inexact? 4) ⇒ #f (inexact? 4.0) ⇒ #t (inexact? 4.00001) ⇒ #t (inexact? 4e0) ⇒ #t (inexact? 4m) ⇒ #t List [8.5.3] Lists are slippery things to define, enough so that they should be the topic of a tutorial of their own. Lists should not be confused with node-lists, which are what many of the style language procedures operate on. Lists are written as a sequence of objects surrounded by parentheses. The list may need to be quoted by a leading single quote (') in some contexts. The empty list, which the a special case of a list with no members, is written (). There is a dotted pair notation for representing pairs of items. The list representation is actually a shorthand form of representing dotted pairs, but since the pair type predicate is not part of the core expression language, pairs will be ignored for now. List Type Predicate [8.5.3.7] (list? obj) Returns #t if obj is a list, otherwise returns #f. (list? '()) ⇒ #t (list? '(Mulberry)) ⇒ #t (list? '(a b c)) ⇒ #t (list? "Mulberry") ⇒ #f (list? '("Mulberry")) ⇒ #t (list? 3) ⇒ #f (list? '(3 4 5)) ⇒ #t (list? #\M) ⇒ #f (list? '(#\M #\T #\I)) ⇒ #t Empty List Type Predicate [8.5.3.6] (null? obj) Returns #t if obj is the empty list, otherwise returns #f. (null? '()) ⇒ #t (null? '(Mulberry)) ⇒ #f (null? '(a b c)) ⇒ #f Character [8.5.8] The character object represents a character. Outside of strings, characters are written as “#\any-character” or as “#\character-name”. Within strings, only the character-name form is allowed, but without the leading “#”. Within strings, character-name should be followed by “;” unless the following character cannot be interpreted as part of character-name. Jade supports Unicode character names. The character name used in the stylesheet should be all lowercase, and any spaces in the official Unicode name should be replaced by hyphens. For example, the Unicode character named “EN DASH” is represented as “#\en-dash” in a stylesheet. #\M Uppercase character “M” #\u Lowercase character “u” #\- Dash character #\en-dash EN DASH character #\ Space character (though you can't see the space after “#\”) #\space The preferred way to write a space "\en-dash" A string containing the EN DASH character "\en-dash;M" A string containing the EN DASH character followed by “M” Character Type Predicate [8.5.8.3] (character? obj) Returns #t if obj is a character, otherwise returns #f. (character? #f) ⇒ #f (character? #\M) ⇒ #t (character? "Mulberry") ⇒ #f (character? 'Mulberry) ⇒ #f String [8.5.9] A sequence of characters. Strings are written as a sequence of characters enclosed in double quotes, ("). Double quote characters within a string are escaped by a backslash (\), and backslash characters are escaped by another backslash: "The \"backslash\" is written as \\." String Type Predicate [8.5.9.1] (string? obj) Returns #t if obj is a string, otherwise returns #f. (string? #f) ⇒ #f (string? #\M) ⇒ #f (string? "Mulberry") ⇒ #t (string? 'Mulberry) ⇒ #f Symbol [8.5.4] Objects that are identical if and only if their names are spelled the same way. Symbols are written with a leading single quote ('), although the quote is not part of the name of the symbol. Any constant string that can be supplied as the value of a characteristic is a symbol. Symbol Type Predicate [8.5.4.1] (symbol? obj) Returns #t if obj is a symbol, otherwise returns #f. (symbol? #f) ⇒ #f (symbol? #\M) ⇒ #f (symbol? "Mulberry") ⇒ #f (symbol? 'Mulberry) ⇒ #t Keyword [8.5.5] Keywords are similar to symbols. Keywords are written with a trailing colon (:), although the colon is not part of the name of the keyword. The characteristic names in a make expression are keywords. Keyword Type Predicate [8.5.5.1] (keyword? obj) Returns #t if obj is a string, otherwise returns #f. (keyword? start-indent:) ⇒ #t (keyword? Mulberry:) ⇒ #t (keyword? "start-indent:") ⇒ #f (keyword? 'Mulberry) ⇒ #f Boolean [8.5.1] The standard objects are #t and #f, but anything except #f evaluates as a true value in a conditional expression. #f, therefore, is the only object that evaluates as a false value. Boolean Type Predicate [8.5.1.2] (boolean? obj) Returns #t if obj is a boolean object, and returns #f otherwise. (boolean? #f) ⇒ #t (boolean? 3) ⇒ #f (boolean? '()) ⇒ #f (boolean? 0) ⇒ #f Procedure [8.5.10] DSSSL doesn't seem to define what a procedure is. “The Scheme Programming Language” by Dybvig describes a procedure as “simply the association of a name with a block of code”. Procedure Call (operator operand*) Calls procedure operator with arguments operand*. Procedure Type Predicate [8.5.10.1] (procedure? obj) Returns #t if obj is a procedure, and returns #f otherwise. (procedure? procedure?) ⇒ #t (procedure? 'procedure?) ⇒ #f (procedure? "procedure?") ⇒ #f (procedure? #\en-dash) ⇒ #f Quick Reference Quantity 4 Exact number 4.0 Inexact number 4e2 Inexact number 4e-1 Inexact number 4m Length (dimension 1) #b1000 Binary representation of decimal 16 #o20 Octal representation of decimal 16 #x10 Hexadecimal representation of decimal 16 Identifier var Variable var: Keyword 'var Symbol (proc var) Procedure '(var1 var2) Quoted list (quote (var1 var2)) Quoted list #\v Character “v” #\var Character named “var” "var" String "\var" Character named “var” within a string "\var;iable" Character named “var” within a string plus “iable” Variable Definition [8.4] (define variable expression) This is a primitive of the expression language syntax. (define var "Mulberry") var ⇒ "Mulberry" The core expression language does not include the syntax production for defining your own procedures. Equivalence [8.5.2] (equal? obj1 obj2) Returns #t of obj1 and obj2 should be regarded as the same object. The conditions for equivalence vary with the type of the objects. equal? returns #t if and only if: obj1 and obj2 are both #t or both #f; obj1 and obj2 are both symbols and (string=? (symbol->string obj1) (symbol->string obj2)) ⇒ #t obj1 and obj2 are both numbers, are numerically equal in the sense of =, and are either both exact or inexact; obj1 and obj2 are both strings and are the same string according to the string=? procedure; obj1 and obj2 are both characters and are the same character according to the char=? procedure; obj1 and obj2 are both the empty list; obj1 and obj2 are both #t or both #f; obj1 and obj2 are both pairs and the car of obj1 is equal? to the car of obj2 and the cdr of obj1 is equal? to the cdr obj2. Equality for procedures is not well defined. See the standard for details. Numerical Expressions Comparison Predicates [8.5.7.7] (= q1 q2 q3 …) (< q1 q2 q3 …) (> q1 q2 q3 …) (<= q1 q2 q3 …) (>= q1 q2 q3 …) These return #t if their arguments match the following conditions: = equal < monotonically increasing > monotonically decreasing <= monotonically nondecreasing >= monotonically nonincreasing (= 2 2) ⇒ #t (= 2 2 2) ⇒ #t (= 2 2 3) ⇒ #f (= 1 2 3) ⇒ #f (= 9 7 5 3) ⇒ #f (= 6 6 3) ⇒ #f (< 2 2) ⇒ #f (< 2 2 2) ⇒ #f (< 2 2 3) ⇒ #f (< 1 2 3) ⇒ #t (< 9 7 5 3) ⇒ #f (< 6 6 3) ⇒ #f (> 2 2) ⇒ #f (> 2 2 2) ⇒ #f (> 2 2 3) ⇒ #f (> 1 2 3) ⇒ #f (> 9 7 5 3) ⇒ #t (> 6 6 3) ⇒ #f (<= 2 2) ⇒ #t (<= 2 2 2) ⇒ #t (<= 2 2 3) ⇒ #t (<= 1 2 3) ⇒ #t (<= 9 7 5 3) ⇒ #f (<= 6 6 3) ⇒ #f (>= 2 2) ⇒ #t (>= 2 2 2) ⇒ #t (>= 2 2 3) ⇒ #f (>= 1 2 3) ⇒ #f (>= 9 7 5 3) ⇒ #t (>= 6 6 3) ⇒ #t Maximum and Minimum [8.5.7.9] (max q1 q2 …) (min q1 q2 …) Returns the maximum or minimum, respectively, of their arguments. The arguments must all have the same dimension, and the result will have the same dimension as the arguments. (max 1 2 3) ⇒ 3 (max 1.0 2 3) ⇒ 3.0 (max 4pt 2pt 6pi) ⇒ 6pi (min 1 2 3) ⇒ 1 (min 1.0 2 3) ⇒ 3.0 (min 4pt 2pt 6pi) ⇒ 2pt Addition [8.5.7.10] (+ q1 …) Returns the sum of its arguments. The arguments should all have the same dimension, and the result will have the same dimension as the arguments. (+) ⇒ 0 (+ 3) ⇒ 3 (+ 1 1) ⇒ 2 (+ 1 3 5 7) ⇒ 16 Subtraction [8.5.7.12] (- q1 q2) (- q) The first case returns the difference between the two arguments. The second case returns the negations of the argument. The arguments should all have the same dimension, and the result will have the same dimension as the arguments. (- 27 3) ⇒ 24 (- 1) ⇒ -1 Multiplication [8.5.7.11] (* q1 …) Returns the product of its arguments. The dimension of the result is the sum of the dimensions of the arguments. (* 2 2) ⇒ 4 (* 4 2) ⇒ 8 (* 4 2pt) ⇒ 8pt Division [8.5.7.13] (/ q1 q2) (/ q) With two arguments, returns the quotient of its arguments. With one argument, returns the reciprocal of its argument. The dimension of the result is the difference of the dimensions of the arguments. With one argument, the dimension of the result is the negation of the dimension of the argument since the number 1 has dimension 0. (/ 27 3) ⇒ 9 (/ 2) ⇒ 1/2 Absolute Value [8.5.7.14] (abs q) Returns the magnitude of its argument. (abs -6) ⇒ 6 Number-theoretic Division [8.5.7.15] (quotient n1 n2) (remainder n1 n2) (modulo n1 n2) These procedures perform integer division (referred to as number-theoretic division in the standard without explaining “number-theoretic”). For the positive integers n1 and n2, if are n3 and n4 integers such that: n1 = n2n3 + n4 and 0 ≤ n4n2 then the following is true: (quotient n1 n2) ⇒ n3 (remainder n1 n2) ⇒ n4 (modulo n1 n2) ⇒ n4 (quotient 17 5) ⇒ 3 (remainder 17 5) ⇒ 2 (modulo 17 5) ⇒ 2 (quotient -17 5) ⇒ -3 (remainder -17 5) ⇒ -2 (modulo -17 5) ⇒ 2 (quotient 17 -5) ⇒ -3 (remainder 17 -5) ⇒ 2 (modulo 17 -5) ⇒ -2 (quotient -17 -5) ⇒ 3 (remainder -17 -5) ⇒ -2 (modulo -17 -5) ⇒ -2 (quotient 17 5.0) ⇒ 3 (remainder 17 5.0) ⇒ 2.0 (modulo 17 5.0) ⇒ 2 Real to Integer Conversion [8.5.7.16] (floor x) (ceiling x) (truncate x) (round x) floor returns the largest integer not larger than x. ceiling returns the smallest integer not smaller than x. truncate returns the integer closest to x whose absolute value is not larger than the absolute value of x. round returns the closest integer to x, rounding to even when x is halfway between two integers. If the argument to one of these procedures is inexact, the result is also inexact. (floor 2.5) ⇒ 2.0 (ceiling 2.5) ⇒ 3.0 (truncate 2.5) ⇒ 2.0 (round 2.5) ⇒ 2.0 (floor 3.6) ⇒ 3.0 (ceiling 3.6) ⇒ 4.0 (truncate 3.6) ⇒ 3.0 (round 3.6) ⇒ 4.0 (floor -2.5) ⇒ -3.0 (ceiling -2.5) ⇒ -2.0 (truncate -2.5) ⇒ -2.0 (round -2.5) ⇒ -2.0 (floor -3.6) ⇒ -4.0 (ceiling -3.6) ⇒ -3.0 (truncate -3.6) ⇒ -3.0 (round -3.6) ⇒ -4.0 Square Root [8.5.7.20] (sqrt q) Returns the square root of q. The dimension of q should be even, and the dimension of the result is half the dimension of q. The square root of a dimensionless quantity is similarly dimensionless. (sqrt 25) ⇒ 5 (sqrt (* 4pt 1pt)) ⇒ 2pt Number to String Conversion [8.5.7.24] (number->string number) (number->string number radix) Returns a string representation of the given number in the given radix, or in radix 10 if radix is omitted. radix may be one of 2, 8, 10, or 16. The result never includes an explicit radix prefix. (number->string 16) ⇒ "16" (number->string 16 2) ⇒ "10000" (number->string 16 8) ⇒ "20" (number->string 16 10) ⇒ "16" (number->string 16 16) ⇒ "10" (number->string #x10) ⇒ "16" (number->string #x10 2) ⇒ "10000" (number->string #x10 8) ⇒ "20" (number->string #x10 10) ⇒ "16" (number->string #x10 16) ⇒ "10" List Expressions List Construction [8.5.3.8] (list obj …) Returns a list of its arguments. (list #\M 1 '(3 4) "abc" 5pt) ⇒ (#\M 1 (3 4) "abc" 5pt) (list) ⇒ () List Length [8.5.3.9] (length list) Returns the length of list. (length '(a b '(c d) e)) ⇒ 4 (length '(#\M 1 '(3 4) "abc" 5pt)) ⇒ 5 (length '()) ⇒ 0 List Appendance [8.5.3.10] (append list …) Returns a list consisting of the members of each of the lists. (append '(a b) '(c d) '(e)) ⇒ (a b c d e) (append '(1) '(2 3 4 5)) ⇒ (1 2 3 4 5) The last argument doesn't have to be a list, but if it isn't, the procedure will return an improper list, and we wouldn't want that, would we? List Reversal [8.5.3.11] (reverse list) Returns a list consisting of the elements in list in reverse order. The order of the elements in list may be reversed, but the reversal does not carry through to any lists within list. (reverse '(a b '(c d) e)) ⇒ (e (c d) b a) (reverse '(#\M 1 '(3 4) "abc" 5pt)) ⇒ (5pt "abc" (3 4) 1 #\M) (reverse '()) ⇒ () Sublist Extraction [8.5.3.12] (list-tail list k) Returns a list consisting of the elements of list omitting the first k elements. (list-tail '(a b '(c d) e) 2) ⇒ (e) (list-tail '(#\M 1 '(3 4) "abc" 5pt) 2) ⇒ ("abc" 5pt) List Access [8.5.3.13] (list-ref list k) Returns the kth element of list. The first element of list is index 0. The returned element, not a list containing the element, is returned. (list-ref '(a b '(c d) e) 2) ⇒ (c d) (list-ref '(#\M 1 '(3 4) "abc" 5pt) 0) ⇒ #\M List Membership [8.5.3.14] (member obj list) Returns a sublist consisting of the elements of list from the first occurrence of obj to the end of the list, otherwise returns #f when obj is not a member of list. (member 'b '(a b '(c d) e)) ⇒ (b (c d) e) (member '(c d) '(a b '(c d) e)) ⇒ ((c d) e) (member 3.14 '(#\M 1 '(3 4) "abc" 5pt)) ⇒ #f Character Expressions Character Comparison Predicate [8.5.8.4] (char=? char1 char2) Returns #t if char1 and char2 are the same character, otherwise returns #f. There are other character comparison predicates that are not included in the core expression language. See Sections 8.5.8.4 and 8.5.8.5 of the DSSSL standard. (char=? #\A #\A) ⇒ #t (char=? #\A #\a) ⇒ #f Character Properties [8.5.8.7] (char-property symbol char) (char-property symbol char obj) Returns the value of the property symbol of char. It is an error if symbol is not a character property. If char does not have a property symbol, then obj is returned, or if obj was not specified, the default value of the property is returned. Jade does not fully support char-property, and it always returns either #f or the default value. String Expressions String Construction [8.5.9.2] (string char …) Returns a string composed of the arguments (string #\M #\u #\l #\b #\e #\r #\r #\y) ⇒ "Mulberry" String Length [8.5.9.3] (string-length string) Returns the number of characters in string. (string-length "Mulberry") ⇒ 8 String Access [8.5.9.4] (string-ref string k) Returns character k of string. The first character of string is index 0. (string-ref "Mulberry" 0) ⇒ #\M String Equivalence [8.5.9.5] (string=? string1 string2) Returns #t if the two strings are the same length and have the same characters in the same positions, otherwise returns #f. (string=? "Mulberry" "Mulberry") ⇒ #t (string=? "Mulberry" "mulberry") ⇒ #f (define var "Mulberry") (string=? "Mulberry" var) ⇒ #t Substring Extraction [8.5.9.7] (substring string start end) Returns the string comprising the characters of string between the start and end indexes inclusive, where the first character of string is index 0. (substring "Mulberry" 3 7) ⇒ "berry" Appending Strings [8.5.9.8] (string-append string …) Returns a string formed by concatenating the argument strings. (string-append "Mul" "berry" "!") ⇒ "Mulberry!" String to Number Conversion [8.5.7.25] (string->number number) (string->number number radix) Returns a number of the maximally precise representation expressed by the given string in the given radix (or in radix 10 if omitted), or #f is string is not a syntactically valid representation for a number. radix may be one of 2, 8, 10, or 16. radix may be overridden by an explicit radix prefix in string, e.g., "#o37". (string->number "17") ⇒ 17 (string->number "17" 2) ⇒ #f (string->number "17" 8) ⇒ 15 (string->number "17" 10) ⇒ 17 (string->number "17" 16) ⇒ 23 (string->number "17.0") ⇒ 17.0 (string->number "1e3") ⇒ 1000.0 (string->number "#x17" 10) ⇒ 23 Procedure Expressions Procedure Application [8.5.10.2] (apply proc args) proc is a procedure, and args is a list. apply calls proc with the elements of args as the actual arguments. (apply * '(2 3)) ⇒ 6 (apply process-matching-children '("PARA" "LIST" "TABLE")) ⇒ sosofos External Procedure [8.5.10.4] (external-procedure string) Returns a procedure object which, when called, executes the external procedure with public identifier string. Returns #f if the system cannot find the external procedure. When the procedure object is evaluated, the arguments passed to the object are passed to the external procedure, and the result of the external procedure is returned as the result of the call of the procedure object. An error may be signaled if the number or type of the arguments passed to the procedure object do not match those expected by the external procedure. (external-procedure "UNREGISTERED::James Clark//Procedure::if-front-page") ⇒ procedure object (define if-front-page (external-procedure "UNREGISTERED::James Clark//Procedure::if-front-page")) (procedure? if-front-page) ⇒ #t (define if-front-page (external-procedure "UNREGISTERED::James Clark//Procedure::if-front-page")) (if-front-page a b) ⇒ Result of external procedure Date and Time Time [8.5.11] (time) Returns an integer for the number of seconds since 1970-01-01 00:00:00 GMT. Time Conversion [8.5.11] (time->string k) (time->string k boolean) Returns a string in the format of ISO 8601 converted from an integer representation as returned by time. If boolean is present and true, the string representation is in GMT, otherwise it is in local time. Error Signaling [8.5.12] (error string) error signals an error, and the argument string describes the error. No value is returned from error. Logical Expressions AND [8.3.2.3] (and test*) The test expressions are evaluated left to right, and if one of them returns a false value, and terminates and returns that value, otherwise it returns the value of the last expression. This means that and will return a value other than #t or #f if the last expression evaluated does not return #t or #f. If there are no test expressions, #t is returned. (and (= 3 3) (> 4 3)) ⇒ #t (and (= 3 3) (< 4 3)) ⇒ #f (and 3 4 5 6) ⇒ 6 (and) ⇒ #t OR [8.3.2.4] (or test*) The test expressions are evaluated left to right, and the first true value is returned. If none of the expressions evaluate to a true value, then the value of the last expression is returned. This means that or will return a value other than #t if the first true value evaluated is not actually #t. If there are no test expressions, #f is returned. (or (= 3 3) (> 4 3)) ⇒ #t (or (= 3 3) (< 4 3)) ⇒ #t (or #f #f #f)) ⇒ #f (or (= 3 4) 7pt 5.5) ⇒ 7pt Negation [8.5.1.1] (not obj) Returns #f if obj evaluates to a true value, otherwise returns #t. (not #t) ⇒ #f (not #f) ⇒ #t (not 0) ⇒ #f (not "Mulberry") ⇒ #f (not 'nil) ⇒ #f (not '()) ⇒ #f (not (or (= 3 3) (> 4 3)) ⇒ #f if, cond, and case Expressions if [8.3.1.5] (if test consequent alternate) First, test is evaluated. If it returns a true value (not necessarily the #t value), then consequent is evaluated and its value is returned, otherwise alternate is evaluated and its value is returned. Both consequent and alternate must be provided as part of the if expression. (if (> 3 4) "Yes" "No") ⇒ "No" (if #t (+ 3 4) -5) ⇒ 7 (if (+ 4 5 6) 6pt "Maybe") ⇒ 6pt cond [8.3.2.1] (cond (test expression)+) (cond (test expression)* (else expression)) The above expressions are a simplification of productions 42 and 43 in Section 8.3.2.1 of the DSSSL standard. The cond expression is evaluated by evaluating each of the test expressions in turn until one returns a true value, then the corresponding expression is evaluated. If all of the test expressions evaluate to false values and there is no else clause, then an error is signaled. If all of the test expressions evaluate to false and there is an else clause, the expression in that clause is evaluated. The value returned from the cond expression is the result of the expression that is evaluated. The full expression language allows two additional forms of the clause with the test expression. (cond ((> 3 4) 'Yes) ((< 3 4) 'No)) ⇒ 'No(define var 4) (cond ((> 3 var) 'Yes) ((< 3 var) 'No)) ⇒ 'No case [8.3.2.2] (case key ((datum*) expression)+)) (case key ((datum*) expression)+) (else expression)) The above expressions are a simplification of productions 45 to 47 in Section 8.3.2.2 of the DSSSL standard. The datum must all be distinct values. The key expression is evaluated, and its result is compared with each datum in turn until a match is found. If the result of evaluating key is equivalent to the value of datum (in the sense of equal?), then the corresponding expression is evaluated. If none of the datum are equivalent to the key and there is no else clause, then an error is signaled. If none of the datum are equivalent to the key and there is an else clause, the expression in that clause is evaluated. The value returned from the cond expression is the result of the expression that is evaluated. (define var 6pi) (case var ((1pi 3pi 5pi) "Odd") ((2pi 4pi 6pi) "Even") ⇒ "Even" The Real Core Expression Language [8.6] Syntax [120] expression = primitive-expression | derived-expression [121] primitive-expression = variable-reference | literal | procedure-call | conditional [122] variable-reference = variable [123] variable = identifier [124] literal = quotation | self-evaluating [125] quotation = 'datum | (quote datum) [126] datum = simple-datum | list [127] simple-datum = boolean | number | character | string | symbol | keyword | glyph-identifier [128] list = (datum*) | 'datum [129] self-evaluating = boolean | number | character | string | keyword | glyph-identifier [130] procedure-call = (operator operand*) [131] operator = expression [132] operand = expression [133] conditional = (if test consequent alternate) [134] test = expression [135] consequent = expression [136] alternate = expression [137] derived-expression = cond-expression | case-expression | and-expression | or-expression [138] cond-expression = (cond cond-clause+) | (cond cond-clause* (else expression)) [139] cond-clause = (test expression) [140] case-expression = (case key case-clause+) | (case key case-clause* (else expression)) [141] key = expression [142] case-clause = ((datum*) expression) [143] and-expression = (and test*) [144] or-expression = (or test*) [145] definition = (define variable expression) Procedures (not obj) (boolean? obj) (equal? obj1 obj2) (null? obj) (list? obj) (list obj …) (length list) (append list …) (reverse list) (list-tail list k) (list-ref list k) (member obj list) (symbol? obj) (keyword? obj) (quantity? obj) (number? obj) (real? obj) (integer? obj) (= q1 q2 q3 …) (< q1 q2 q3 …) (> q1 q2 q3 …) (<= q1 q2 q3 …) (>= q1 q2 q3 …) (max q1 q2 …) (min q1 q2 …) (+ q1 …) (* q1 …) (- q1 q2) (- q) (/ q1 q2) (/ q) (abs q) (quotient n1 n2) (remainder n1 n+) (modulo n1 n2) (floor x) (ceiling x) (truncate x) (round x) (sqrt x) (number->string number) (number->string number radix) (string->number string) (string->number string radix) (char? obj) (char=? char1 char2) (char-property symbol char) (char-property symbol char obj) (string? obj) (string char …) (string-length string) (string-ref string k) (string=? string1 string2) (substring string start end) (string-append string …) (procedure? obj) (apply proc args) (external-procedure string) (time) (time->string k) (time->string k boolean) (error string) Exercise Identify the type of each of the following: "Mulberry" ⇒ 'Mulberry ⇒ Mulberry: ⇒ #\Mulberry ⇒ "\Mulberry;" ⇒ 99999m ⇒ 2.4 ⇒ 6 ⇒ #x23 ⇒ #b1010 ⇒ #o17 ⇒ 3.4pi ⇒ #\M ⇒ '(Mul berry) ⇒ (mulberry 1 2 4) ⇒ Evaluate the following expressions: (+ 1 2 4) ⇒ (+ 1 2.0 4) ⇒ (- 7) ⇒ (- 4 3) ⇒ (* 4 3) ⇒ (/ 1) ⇒ (/ 7 42) ⇒ (abs -7.5) ⇒ (abs 6) ⇒ Evaluate the following expressions: (= 1 2 4) ⇒ (= 1.0 1) ⇒ (define var 1.0) ⇒ (= var 1.0) ⇒ (< 2 5 5 7) ⇒ (> 2 5 5 7) ⇒ (<= 2 5 5 7) ⇒ (<= 2 5 5 7) ⇒ (< 9pi 4.5pi 2.25pi) ⇒ (> 9pi 4.5pi 2.25pi) ⇒ (<=9pi 4.5pi 2.25pi) ⇒ (<=9pi 4.5pi 2.25pi) ⇒ Evaluate the following expressions: (min 4 5.1 2) ⇒ (max 3pi 1pi 35pt) ⇒ Evaluate the following expressions: (quotient 15 4) ⇒ (remainder 15 4) ⇒ (modulo 15 4) ⇒ (quotient -15 4) ⇒ (remainder -15 4) ⇒ (modulo -15 4) ⇒ (quotient -15 -4) ⇒ (remainder -15 -4) ⇒ (modulo -15 -4) ⇒ (quotient -15 4.0) ⇒ (remainder -15 4.0) ⇒ (modulo -15 4.0) ⇒ Evaluate the following expressions: (floor -2.3) ⇒ (ceiling -2.3) ⇒ (truncate -2.3) ⇒ (round -2.3) ⇒ Evaluate the following expressions: (number->string 12) ⇒ (number->string 12 2) ⇒ (number->string 12 8) ⇒ (number->string 12 10) ⇒ (number->string 12 16) ⇒ Evaluate the following expressions: (list) ⇒ (list "Mulberry") ⇒ (list 1 2 3 4 5 6) ⇒ (length '(1 3 5)) ⇒ (define var '(1 2)) ⇒ (append var var var) ⇒ (reverse '(z '(q m) f)) ⇒ (list-tail '(q w e r t y) 3) ⇒ (list-ref '(q w e r t y) 3) ⇒ (member 'r '(q w e r t y)) ⇒ (member 'r '(q w '(e r) t y)) ⇒ Evaluate the following expressions: (char=? #\i #\l) ⇒ (char=? #\t #\t) ⇒ Evaluate the following expressions: (string #\m #\t #\i) ⇒ (string-length "a \en-dash; z") ⇒ (string=? "blue" "red") ⇒ (define red "blue") ⇒ (string=? "blue" red) ⇒ (substring "Rockville" 1 4) ⇒ (string-append "red" "white" "blue") ⇒ Evaluate the following expressions: (apply max '(3 3.5 9)) ⇒ (apply string-append '("the " "cat " "in " "the " "hat")) ⇒ What is wrong with each of the following expressions? (max 2 2.0 2pi 2e0) ⇒ (sqrt 2pi) ⇒ (string=? "\en-dash" #\en-dash) ⇒ (list-tail '(a 2pi 2.0 b) 2.0) ⇒ Evaluate the following expressions: (if (<= 5 6 7 7 8.0) "Yes" "No") ⇒ (define red "blue") (if (not (string=? red "blue")) (max 4 5.0 6 7.0) (min 4 5.0 6 7.0)) ⇒ (define var (/ 0.5)) (case var ((1 2 3 4) "Exact") ((1.0 2.0 3.0 4.0) "Inexact")) ⇒ (define seven 6) (define six 7) (define five 5) (cond ((< five six seven) 'one) ((max five six seven) 'two) (else 'three)) ⇒