我是SML的新手,也不太了解语法。
我正在练习检查回文而不反转列表。这是我的代码
fun symmetric(i,n,inlist) =
if List.nth(inlist,i-1) = List.nth(inlist,n-i)
then true
else
false;
fun palindrome(n, inlist) =
let
val i = ref 1
in
while !i < n do (
if symmetric(!i,!n,!inlist) = false
then false
else ()
i := !i + 1
)
true
end;
我只在有趣的回文中遇到错误,但我自己无法解决。
答案 0 :(得分:4)
您甚至可以在不将字符串转换为列表的情况下制作回文检查器:
fun palindrome s =
let fun check i j =
i >= j orelse
String.sub (s, i) = String.sub (s, j) andalso
check (i+1) (i-1)
in check 0 (String.size s - 1) end
以下是您的代码的一些反馈:
当然,请考虑使用递归而不是迭代。
非功能性程序员的一个常见问题是,他们似乎只是为了副作用而连续执行许多语句。在函数式编程中,您非常依赖每个表达式的值来指导程序的结果。但 是一个;
运算符,它可以像这样使用:
fun palindrome s =
let val i = ref 0
val j = ref (String.size s - 1)
val result = ref true
in while !i < !j do
(if String.sub (s, !i) = String.sub (s, !j)
then (i := !i + 1 ; j := !j - 1)
else (i := !j ; result := false))
; !result
end
但是,如果你想连续做多件事,那么let-expression就像;
运算符一样整洁。
代码
if A = false
then false
else B
可以写成
if not (A)
then false
else B
可以进一步改进为
if A
then B
else false
与
完全相同A andalso B
所以道德是:
A = false
,请写not A
(而不是A = true
,写下A
)。if ... then <true/false> else <true/false>
和andalso
的某种组合替换orelse
。也就是说,当结果类型是 bool 时, if-then-else 永远不需要(但如果逻辑很复杂,你可能仍然喜欢它。)答案 1 :(得分:3)
如果反对列表的限制旨在禁止使用内置rev
而不是隐式反转列表的计算,则这里是基于堆栈的方法。我们的想法是将字符推入堆栈(表示为列表),然后将其弹出,并根据原始字符列表进行检查。如果堆栈或原始列表首先清空,或者弹出的项目与原始列表中的相应字符不匹配 - 它不是plalindrome
fun pushAll [] stack = stack
| pushAll (x::xs) stack = pushAll xs (x::stack)
fun popCheck [] [] = true
| popCheck [] _ = false
| popCheck _ [] = false
| popCheck (x::xs) (y::ys) = x = y andalso popCheck xs ys
fun palindrome s =
let val chars = explode s
val stack = pushAll chars []
in
popCheck chars stack
end;