Racket中的基本if-s

时间:2018-04-02 08:41:36

标签: scheme racket

我正在尝试编写一个基本程序,将给定参数与某个字符进行比较。我意识到运算符(define test (lambda testChar (if (char=? testChar 'a) 3 2) ) ) 只比较两个数字,所以我尝试使用字符比较运算符。

起初我做了:

(define test
   (lambda testChar
     (if (equal? testChar 'a) 3 2)
   )
)

但是我收到一条错误,说我没有使用正确类型的表达式。消息是:

  

char = ?:合同违规     预期:char?     给出:'(" a")     论点位置:1     其他论点......:

所以我尝试使用不同的运算符:

(test 'a)

这次我能够运行它。但是当在2上运行时,我收到eqv?,这意味着if中的条件不适用。如果我使用equal?而不是eq,也会发生相同的情况。

我相信我在这里缺少一些基本的东西,无论是在Racket中的字符,还是if条件。它是什么?

编辑:我也尝试了.container-login100 { width: 100%; min-height: 100vh; display: -webkit-box; display: -webkit-flex; display: -moz-box; display: -ms-flexbox; display: flex; flex-wrap: wrap; justify-content: center; align-items: center; padding: 15px; background: #9053c7; background: -webkit-linear-gradient(-135deg, #c850c0, #4158d0); background: -o-linear-gradient(-135deg, #c850c0, #4158d0); background: -moz-linear-gradient(-135deg, #c850c0, #4158d0); background: linear-gradient(-135deg, #c850c0, #4158d0); } 运算符,但它仍然返回false。

2 个答案:

答案 0 :(得分:1)

OP的问题和(自我)答案有几个问题。

试图让任何绊倒这个问题的人具体化,其他人试图向OP指出这些问题......

比较整数

与许多其他语言一样,在Racket中,一种表示整数类型数字文字的方法是使用一串数字。

要使用 if 表单将一个整数与另一个整数进行比较,可以使用 = 运算符:

#lang racket

(define num-val 65) ;; code-point for upper case letter 'A'

num-val

(define test-num
  (lambda (testNumber)
   (if (= testNumber 65)
       "test-num using = gives true"
       "test-num using = gives false")))

(format "test against the defined num-val: ~a" (test-num num-val))
(format "test against number value 66: ~a" (test-num 66))

在DrRacket中运行时给出以下内容:

65
"test against the defined num-val: test-num using = gives true"
"test against number value 66: test-num using = gives false"

比较字符

在Racket中,表示字符类型常量文字的一种方法是使用序列#\,例如#\ A,#\ Z,#\ a,#\ A,#\ 0,#\ 9等

要使用 if 表单比较一个字符,可以使用 char =?运算符,例如:

#lang racket

(define num-val 65) ;; code-point for upper case letter 'A'
(define char-val (integer->char num-val))

char-val
(char->integer char-val)

(define test-char
  (lambda (testCharacter)
   (if (char=? testCharacter #\A)
       "test-char using char=? gives true"
       "test-char using char=? gives false")))

(format "test against the defined char-val: ~a" (test-char char-val))
(format "test against upper case letter 'A': ~a" (test-char #\A))
(format "test against lower case letter 'a': ~a" (test-char #\a))

给出(再次在DrRacket中):

#\A
65
"test against the defined char-val: test-char using char=? gives true"
"test against upper case letter 'A': test-char using char=? gives true"
"test against lower case letter 'a': test-char using char=? gives false"

比较符号

在Racket中,符号是一个单独的东西,表示符号的一种方法是使用单个前导撇号,例如' A,' Apple,' bbb,' xyz等。

无法比较字符和符号(没有某种转换):

(test-char 'A) ;; BAD - the symbol 'A is not a char: gives contract violation error:
#|
char=?: contract violation
  expected: char?
  given: 'A
  argument position: 1st
  other arguments...:
|#

比较字符串

与其他语言一样,Racket字符串类型的常量文字用双引号分隔,例如" Apple","苹果," 1"," 999"等。

与符号一样,字符串无法与字符进行比较:

(test-char "A") ;; BAD - the string "A" is not a char: gives contract violation error:
#|
char=?: contract violation
  expected: char?
  given: "A"
  argument position: 1st
  other arguments...:
|#

使用eq进行比较?和平等?

Racket中存在其他比较运算符,例如eq?,eqv?等于?。

但是在使用eq比较字符(或其他任何内容)时要小心吗?并且相等?人们通常希望比较对象'值(即使用相等的?),而不是对象的比较'身份(即使用eq?)。 (对象的标识值可以显示为该对象存储在内存中的地址,而值是特定对象表示的内容。)

等于?字符有时也是eq?

对于字符类型,Racket文档声明对于前256个字符,应该期望eq?和平等?返回由integer-> char返回的字符的相同值。这意味着整数 - > char表示对前256个字符使用某种缓存。

#lang racket

(define test-char
  (lambda (testChar)
   (if (char=? testChar #\A)
       "test-char using char=? gives true"
       "test-char using char=? gives false")))

(define test-char-eq
  (lambda (testChar)
   ; Warning: eq? compares object identity, compare with test-char-equal
   (if (eq? testChar (integer->char 65))
       "test-char-eq using eq? gives true"
       "test-char-eq using eq? gives false")))

(define test-char-equal
  (lambda (testChar)
   ; Warning: equal? compares object values, compare with test-char-eq
   (if (equal? testChar (integer->char 65))
       "test-char-equal using equal? gives true"
       "test-char-equal using equal? gives false")))

(format "test an ASCII object (code-point 65) identity: ~a" (test-char-eq (integer->char 65)))
(format "test an ASCII object (code-point 65) value: ~a" (test-char-equal (integer->char 65)))
(format "test an ASCII object (code-point 66) identity ~a" (test-char-eq (integer->char 66)))
(format "test an ASCII object (code-point 66) value: ~a" (test-char-equal (integer->char 66)))

给出:

"test an ASCII object (code-point 65) identity: test-char-eq using eq? gives true"
"test an ASCII object (code-point 65) value: test-char-equal using equal? gives true"
"test an ASCII object (code-point 66) identity test-char-eq using eq? gives false"
"test an ASCII object (code-point 66) value: test-char-equal using equal? gives false"

表示Unicode字符

在Racket中表示整数类型常量文字的另一种方法,可能对于例如非ASCII字符常量文字,与序列#x,例如#x221e等。字符类型常量文字也可以使用类似#\ u的序列在Racket中指定,例如#\ u221e等。

#lang racket

(define num-val-non-ASCII #x221e) ;; code-point for the infinity symbol
(define char-val-non-ASCII (integer->char num-val-non-ASCII))

num-val-non-ASCII
char-val-non-ASCII

(define test-char-eq
  (lambda (testChar)
   (if (eq? testChar (integer->char #x221e))
       "test-char-eq using eq? gives true"
       "test-char-eq using eq? gives false")))

(define test-char-equal
  (lambda (testChar)
   (if (equal? testChar (integer->char #x221e))
       "test-char-equal using equal? gives true"
       "test-char-equal using equal? gives false")))

(format "test against the non-ASCII character identity: ~a" (test-char-eq char-val-non-ASCII))
(format "test against the non-ASCII character value: ~a" (test-char-equal char-val-non-ASCII))

#\u221e
(char->integer #\u221e)

(format "test a non-ASCII character constant identity: ~a" (test-char-eq #\u221e))
(format "test a non-ASCII character constant value: ~a" (test-char-equal #\u221e))

这给出了:

8734
#\∞
"test against the non-ASCII character identity: test-char-eq using eq? gives false"
"test against the non-ASCII character value: test-char-equal using equal? gives true"
#\∞
8734
"test a non-ASCII character constant identity: test-char-eq using eq? gives true"
"test a non-ASCII character constant value: test-char-equal using equal? gives true"

注意: - 8734十进制是221E十六进制 - eq?和平等?为此代码点返回integer-> char返回的字符的不同值 - 两个方程?和平等?在比较#\ u表示法产生的字符对象时返回true(至少与Windows上的Racket的当前实现相比)。

扩展的Unicode字符

也可以使用Unicode字符集中的更多字符:

#lang racket

(define unicode-num-val #x1f47a) ;; code-point for the "Japanese Goblin" symbol
(define unicode-char-var (integer->char unicode-num-val))

unicode-num-val
unicode-char-var

(define test-char-eq
  (lambda (testChar)
   (if (eq? testChar (integer->char unicode-num-val))
       "test-char-eq using eq? gives true"
       "test-char-eq using eq? gives false")))

(define test-char-equal
  (lambda (testChar)
   (if (equal? testChar (integer->char unicode-num-val))
       "test-char-equal using equal? gives true"
       "test-char-equal using equal? gives false")))

(format "test an unicode object identity: ~a" (test-char-eq (integer->char unicode-num-val)))
(format "test an unicode object value: ~a" (test-char-equal (integer->char unicode-num-val)))

这给出了:

128122
#\
"test an unicode object identity: test-char-eq using eq? gives false"
"test an unicode object value: test-char-equal using equal? gives true"

注意: - 128122十进制是1F47A十六进制 - eq?和平等?并为此Unicode字符赋予不同的值(至少是Windows上当前的Racket实现)

等于?字符串并不总是eq?

回想一下,在Racket中,字符串类型常量文字由双引号分隔,例如" Apple"," Apples"等,但也可以使用 string 形式创建字符串类型常量文字,例如(字符串#\ A#\ p#\#p#\ l#\ e),(字符串#\ A#\ p#\ p#\ l#\ e,#\ s)等。

#lang racket

(define string-val "Apple")

string-val

(define test-str-eq
  (lambda (testString)
   ; Warning: eq? compares object identity (contrast with test-str-equal)
   (if (eq? testString "Apple")
       "test-str-eq using eq? gives true"
       "test-str-eq using eq? gives false")))

(define test-str-equal
  ; Warning: equal? gives value comparison (contrast with test-str-eq)
  (lambda (testString)
   (if (equal? testString "Apple")
       "test-str-equal using equal? gives true"
       "test-str-equal using equal? gives false")))

(format "test against the defined string-val object identity: ~a" (test-str-eq string-val))
(format "test against the defined string-val object value: ~a" (test-str-equal string-val))

(format "test against the constant string \"Apple\" object identity: ~a" (test-str-eq "Apple"))
(format "test against the constant string \"Apple\" object value: ~a" (test-str-equal "Apple"))

(format "test against the constant string \"Apples\" object identity: ~a" (test-str-eq "Apples"))
(format "test against the constant string \"Apples\" object value: ~a" (test-str-equal "Apples"))

(define created-string-val (string #\A #\p #\p #\l #\e))

created-string-val

(format "test against the created string object identity: ~a" (test-str-eq created-string-val))
(format "test against the created string object value: ~a" (test-str-equal created-string-val))

这给出了:

"Apple"
"test against the defined string-val object identity: test-str-eq using eq? gives true"
"test against the defined string-val object value: test-str-equal using equal? gives true"
"test against the constant string \"Apple\" object identity: test-str-eq using eq? gives true"
"test against the constant string \"Apple\" object value: test-str-equal using equal? gives true"
"test against the constant string \"Apples\" object identity: test-str-eq using eq? gives false"
"test against the constant string \"Apples\" object value: test-str-equal using equal? gives false"
"Apple"
"test against the created string object identity: test-str-eq using eq? gives false"
"test against the created string object value: test-str-equal using equal? gives true"

注意等于?字符串可能并不总是eq?。

当比较字符类型对象和在代码中以不同方式创建的字符串类型对象时,eq?的结果的差异很可能是当前Racket实现的工件。错误使用eq?可能会导致特别难以找到的错误。

使用平等吗? vs eq?

通常人们会想要与对象的值进行比较(即使用equal?),而不是与对象的身份进行比较(即使用eq?),即使他们有时会给出相同的结果。

比较不同类型的对象

球拍是无类型的,方程式?和平等?接受不同类型的对象,并使用不同类型的对象进行比较将始终导致false:

#lang racket

(define test-str-eq
  (lambda (testString)
   ; Warning: eq? compares object identity (contrast with test-str-equal)
   (if (eq? testString "Apple")
       "test-str-eq using eq? gives true"
       "test-str-eq using eq? gives false")))

(define test-str-equal
  ; Warning: equal? gives value comparison (contrast with test-str-eq)
  (lambda (testString)
   (if (equal? testString "Apple")
       "test-str-equal using equal? gives true"
       "test-str-equal using equal? gives false")))

(test-str-eq 'Apple) ;; BAD - symbol 'Apple is not a string: returns "false" 
(test-str-equal 'Apple) ;; BAD - symbol 'Apple is not a string: returns "false" 

给出了:

"test-str-eq using eq? gives false"
"test-str-equal using equal? gives false"

有关添加类型检查的Racket变体,请参阅Typed-Racket。

比较字符串

的字符

可以使用string-ref访问字符串的各个字符,并且可以将这些字符与 char =?进行比较,如上所述:

#lang racket

(define string-val "Apple")

string-val
(string-ref string-val 0)
(string-ref string-val 1)

(define test-char
  (lambda (testCharacter)
   (if (char=? testCharacter #\A)
       "test-char using char=? gives true"
       "test-char using char=? gives false")))

(format "test against first character of string \"Apple\": ~a" (test-char (string-ref string-val 0)))
(format "test against second character of string \"Apple\": ~a" (test-char (string-ref string-val 1)))

给出了:

"Apple"
#\A
#\p
"test against first character of string \"Apple\": test-char using char=? gives true"
"test against second character of string \"Apple\": test-char using char=? gives false"

请注意,字符串的第一个字符是使用string-ref为0获得的,字符串的第二个字符是使用string-ref为1获得的。

比较字节字符串

Racket还具有与常规(字符)字符串类型不同的字节串类型(一系列字节)。字节字符串常量文字是字符串常量文字,前缀为哈希(a.k.a.磅)符号。

不出所料,将字符串值与字节串值进行比较将返回false:

#lang racket

(define string-val "Apple")
(define byte-string-val #"Apple")

string-val
byte-string-val

(define test-str-equal
  ; Warning: equal? gives value comparison (contrast with test-str-eq)
  (lambda (testString)
   (if (equal? testString string-val)
       "test-str-equal using equal? gives true"
       "test-str-equal using equal? gives false")))

(format "test against the defined byte-string-val: ~a" (test-str-equal byte-string-val))
(format "test against the byte-string #\"Apple\": ~a" (test-str-equal #"Apple"))
(format "test against the byte-string #\"Apples\": ~a" (test-str-equal #"Apples"))

给出了:

"Apple"
#"Apple"
"test against the defined byte-string-val: test-str-equal using equal? gives false"
"test against the byte-string #\"Apple\": test-str-equal using equal? gives false"
"test against the byte-string #\"Apples\": test-str-equal using equal? gives false"

比较字节字符串对象值会产生预期结果:

#lang racket

(define byte-string-val #"Apple")

byte-string-val

(define test-bytes-eq
  ; Warning: eq? gives identity comparison, contrast with test-bytes-equal?
  (lambda (testByteString)
   (if (eq? testByteString #"Apple")
       "test-bytes-eq using eq? gives true"
       "test-bytes-eq using eq? gives false")))

(define test-bytes-equal
  ; Warning: equal? gives value comparison, contrast with test-bytes-eq
  (lambda (testByteString)
   (if (equal? testByteString #"Apple")
       "test-bytes-equal using equal? gives true"
       "test-bytes-equal using equal? gives false")))

(format "test against the defined byte-string-val object identity: ~a" (test-bytes-eq byte-string-val))
(format "test against the defined byte-string-val object value: ~a" (test-bytes-equal byte-string-val))

(format "test against the byte-string #\"Apple\" object identity: ~a" (test-bytes-eq #"Apple"))
(format "test against the byte-string #\"Apple\" object value: ~a" (test-bytes-equal #"Apple"))

(format "test against the byte-string #\"Apples\" object identity: ~a" (test-bytes-eq #"Apples"))
(format "test against the byte-string #\"Apples\" object value: ~a" (test-bytes-equal #"Apples"))

给出了:

#"Apple"
"test against the defined byte-string-val object identity: test-bytes-eq using eq? gives true"
"test against the defined byte-string-val object value: test-bytes-equal using equal? gives true"
"test against the byte-string #\"Apple\" object identity: test-bytes-eq using eq? gives true"
"test against the byte-string #\"Apple\" object value: test-bytes-equal using equal? gives true"
"test against the byte-string #\"Apples\" object identity: test-bytes-eq using eq? gives false"
"test against the byte-string #\"Apples\" object value: test-bytes-equal using equal? gives false"

答案 1 :(得分:-3)

对于在Scheme / Racket中遇到类似奇怪行为的任何人。它发生的原因是因为我错误地定义了函数中的参数。应该是:'(lambda (testChar)而不是我写的'(lambda testChar。这解决了这一切。