number_in_month练习(计数列表中的元素) [英] number_in_month exercise (Count elements in a list)

查看:74
本文介绍了number_in_month练习(计数列表中的元素)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试对整数三元组列表中的元素进行计数,这等于使用SML的给定整数,但是它不起作用.谁能帮我弄清楚下面的代码有什么问题或为我弄清楚吗?

I have been trying to count elements in a list of integer 3-tuples, that equals a given integer using SML, but it's not working. Can anyone help me figure out what's wrong with the below code or straighten it up for me?

 fun number_in_month(x : int*int*int list, m: int) =
    if null x then 0

         else
           let fun inc x = x + 1;
         in
             val counter = 0;
             if m = #2 (hd x) andalso m > 0 then inc counter
            number_in_month((tl x), m)
           `  else
             number_in_month((tl x), m)
        end

该函数应该返回m等于列表中每个元组的第二个元素的次数.

This function is supposed to return the number of times m equals to the second element of each tuple in the list.

推荐答案

很显然,您很难放弃您的当务之急.

Clearly you have a hard time to let go of your imperative thinking.

让我尝试解决您的一些问题

Let me try and address some of your issues

  • 您应该使用模式匹配,而不要使用null xhd xtl x. 这也适用于分解元组和记录.例如

  • You should be using pattern matching instead of using null x, hd x and tl x. This also apply to decomposing tuples and records. For example

fun number_in_month ((x1, x2, x3) :: xs, m) = ...

或者,因为我们从不使用x1和x3

or, since we don't ever use x1 and x3

fun number_in_month ((_, x2, _) :: xs, m) = ...

这样,可以清楚地看到第一个参数是一个三元组列表,并且没有类型注释 需要

This way it is clearly seen that the first argument is a list of 3-tuples, and no type annotation is needed

此外,当您省略显式类型注释时,这就是拥有类型系统的整个想法 可以为您推断出它们(请参阅下一点),然后输入此代码

Also when you omit the explicit type annotation, which is the whole idea of having a type system that can infer them for you (see next point), then this code

fun foo42 xs = map (fn x => #2 x) xs

在未解决的弹性记录"上会给您带来一些讨厌的错误(此错误消息来自SML/NJ)

will give you some nasty errors on "unresolved flex record" (this error message is from SML/NJ)

/tmp/sml20620PlF:105.5-105.44 Error: unresolved flex record
   (can't tell what fields there are besides #2)

可通过分解三元组轻松修复

which is easily fixed by decomposing the 3-tuple

fun foo42 xs = map (fn (_, x2, _) => x2) xs

  • 谈到类型注释. (几乎总是)不需要它们,并且它们使 代码的可读性.更不用说它们不必要地限制了您的功能类型 可以用于.

  • Speaking of type annotations. They are (almost always) not needed, and they clutter up the readability of the code. Not to mention that they unnecessarily restricts the types you function may be used on.

    根据您的实际意愿,您给定的类型注释也是错误的.你 应该在int * int * int周围加上括号.目前,它被解释为 由两个整数组成的三元组和一个整数列表int * int * (int list).

    Also the type annotation you have given is erroneous according to what you really wan't. You should have places parenthesis around the int * int * int. Currently it is interpreted as a 3-tuple of two ints and an int list int * int * (int list).

    如果您确实坚持使用类型注释功能,则可以这样做

    If you really insist in type annotating your function, then you can do it like this

    val number_in_month : (int * int * int) list * int -> int = 
        fn ([]            , m) => 0
         | ((_,x2,_) :: xs, m) => 42
    

    这与Haskell几乎一样,在其中,类型恰好在函数声明之前给出.

    This is "almost" like Haskell, where the type is given just before the function declaration.

    尝试使代码缩进的方式更加一致.这样可以使您更加清楚. 在这里,我特别考虑的是您缩进else部分到in ... end的方式 部分.下面的部分显然在许多我无法想象的方面仍然是错误的,但是它 给出了如何做的想法

    Try to be more consistent in they way you indent your code. That will give you better clarity. Here I'm specifically thinking of the way you have indented the else part end the in ... end part. The below part is clearly still erroneous in so many ways i can't begin to imagine, but it gives an idea as how to do it

    fun number_in_month(x : int*int*int list, m: int) =
        if null x then 0
        else
          let fun inc x = x + 1;
          in
            val counter = 0;
            if m = #2 (hd x) andalso m > 0 then
               inc counter
               number_in_month((tl x), m)
            else
               number_in_month((tl x), m)
          end
    

  • 您不能在let表达式的in ... end部分内声明变量val counter = 0. let表达式的语义是

  • You can't declare a variable val counter = 0 inside the in ... end part of a let-expression. The semantics of a let-expression is

    let
      dec
    in
      exp_1; ...; exp_n
    end
    

    因此,所有声明(函数和值绑定等)都必须放在let ... in部分.

    thus all declarations (function and value bindings, etc) must go in the let ... in part.

    地球上不需要增量功能,它只会使可读性混乱. 请记住,SML使用单一分配,因此变量在声明后是不可变的.

    There is no need on earth to have an increment function, it just clutters the readability. Remember that SML uses single assignment, thus variables are immutable after they are declared.

    嵌套的if-expression内部的序列事物

    The sequence-thing inside your nested if-expression

    inc counter
    number_in_month((tl x), m)
    

    完全没有道理.您可以在其中包含多个表达式的唯一方法 then ... else部分(实际上是任何需要单个表达式的地方)都带有 序列(exp_1; ...; exp_n).但是,仅当最后一个表达式之外的所有表达式都具有 副作用,因为其结果被忽略/扔掉了

    makes absolutely no sense. The only way you can have more than one expression inside the then ... else part (actually any place, where a single expression is expected), is with a sequence (exp_1; ...; exp_n). However this is only usable when all but the last expression has side effect(s), as their results is ignored/thrown away

    - (print "Foo\n"; print "Bar\n"; 42);
    Foo
    Bar
    val it = 42 : int
    

  • 如果您在SO上进行一些搜索,您会发现最近有一个非常相似的问题被提出已答复.尽管最后一个参数的类型有所不同,但是您仍然可以获得一些有用的指针.

    If you search a bit here on SO, you will see that a quite similar question has recently been asked and answered. Though it differs in the the type of the last argument, you might still get some useful pointers.

    总而言之,解决方案可能看起来像

    All in all a solution might look like

    fun number_in_month ([], _) = 0
      | number_in_month ((_,x2,_) :: xs, m) = 
        if x2 = m then
          1 + number_in_month(xs, m)
        else
          number_in_month(xs, m)
    

    但是,由于您的问题比前面提到的问题简单,因此您可以轻松地使用基础库中列表模块中的一些高阶函数

    However since your problem is simpler than the previously stated one, you could easily use some of the higher-order functions from the list module in the basis library

    fun number_in_month (xs, m) = length (List.filter (fn (_, x2, _) => x2 = m) xs)
    

    或者甚至(可以说更简单),将其折叠在列表上,并在每次匹配时以递增的方式递增变量

    Or even (arguably) simpler, by folding over the list and incrementing a variable along the way each time it matches

    fun number_in_month (xs, m) = foldl (fn ((_, x2, _), b) => if x2 = m then b+1 else b) 0 xs
    

    这篇关于number_in_month练习(计数列表中的元素)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆