What is wrong with my code in sml?

后端 未结 1 1460
野的像风
野的像风 2020-12-22 10:25

I don\'t know why my code doesn\'t work.

fun lookup _ [] = 0
  | lookup key ((k,v)::entries) =
    if k = key
    then v
    else (lookup key entries)


        
相关标签:
1条回答
  • 2020-12-22 11:07

    There's nothing wrong with your code, you just didn't call lookup with enough arguments. You make a common mistakes among beginner SML programmers coming from other languages. I'll try to clarify that.

    First, the most important thing to know about functions in Standard ML is this:

    All functions in Standard ML take exactly one argument.

    You might be confused at this point, because your lookup function looks as if it's taking two arguments. It kind of does, but not really.

    There are two main "workarounds" (I'm using quotes because this is actually a great feature of the language) for representing functions that take multiple arguments:

    1. Using curried functions

    If you need to write a function which, conceptually, needs three arguments, then you'd write this:

    fun quux a =
      fn b =>
        fn c =>
          (* do something with a, b and c *)
    

    So, quux is:

    • a function, which takes an argument a and returns
    • a function, which takes an argument b and returns
    • a function, which takes an argument c and returns
    • the result computed using a, b and c

    How would you call quux? Like this, right?

    ((quux a) b) c
    

    But function application is already left associative, so we can actually write this:

    quux a b c
    

    We don't need parentheses to "call" functions! In Standard ML parentheses don't mean "call this function". They're used just for grouping expressions together when you want to change associativity, like in mathematics: (1 + 2) * 3.

    Because defining quux as above is really cumbersome, there's a syntactic shortcut in the language. Instead of writing this:

    fun quux a =
      fn b =>
        fn c =>
          (* do something with a, b and c *)
    

    We can write just this:

    fun quux a b c = (* do something with a, b and c *)
    

    But, they're the same thing. quux is still a function which takes just argument a and returns a new function with argument b, which returns a new function which argument c.

    Ok, so that was one way of representing multi-argument functions in Standard ML. It's also the one you used to define lookup.

    2. Using tuples

    Another common way of representing multi-argument functions is to accept a tuple (which may have from 2 to as many components as you wish). Here's the above example using a tuple now:

    fun quux args =
      case args of
        (a,b,c) => (* do something with a, b and c *)
    

    How could we call quux now? Like this:

    quux (a,b,c)
    

    Notice that I put a space between quux and the tuple. It's optional, but I do it all the time to keep remembering that function application in standard ML is not represented by parentheses. quux gets called because it's been put before the tuple (a,b,c). Tuples, however, do require parentheses, which is why you're seeing them above.

    Again, as before, it's cumbersome to define quux like this:

    fun quux args =
      case args of
        (a,b,c) => (* do something with a, b and c *)
    

    So we can actually use another great feature of the language, pattern matching in argument position, that lets us write this:

    fun quux (a,b,c) = (* do something with a, b and c *)
    

    Ok, now we can really answer your question.


    You defined lookup using the curried function syntax:

    fun lookup _ [] = 0
    

    But you "called" lookup using the tuple syntax, where 1 is the first element of the tuple and [(1,2),(2,3)] is the second element.

    lookup (1, [(1,2),(2,3)])
    

    Why doesn't the compiler complain, though. In this unfortunate case, it doesn't because it happens that the type of the first argument of lookup is a tuple. So, you've basically called lookup with a single argument.

    What you wanted was this:

    lookup 1 [(1,2),(2,3)]
    

    Notice that I'm not defining a tuple anymore.

    0 讨论(0)
提交回复
热议问题