>

목록의 레코드를 업데이트하기 위해 SML 프로그램을 작성하고 있습니다 (예 : person_name 유형이 있습니다.

type person_name = {fname:string, lname:string, mname:string}

그러면 person_name이 포함 된 person_bio가 있습니다.

type person_bio = {age:real, gender:string, name:person_name, status:string}

다음에는 person_bio를 가진 직원이 있습니다.

type employee = {p:person_bio, payrate:real, whours:real} list;

이제 이름을 전달하여 'updateLastName'함수를 정의해야합니다.

현재, 아래 데이터로 하나의 레코드 'e1'을 생성했습니다.

{p={age=40.0,gender="M",name{fname="rob",lname="sen",mname=""},status="M"},
  payrate=30.0,whours=10.0}

하지만 목록을 탐색 한 다음 한 필드를 업데이트하는 데 어려움을 겪고 있습니다.

fun updateLastName(x:string,l:employee)=
  if (L=[]) then []
  else if (x= #fname(#name(#p hd l))  //cheking name of 1st record in list
  //not getting how to update,this kind of line did not work
  #fname(#name(#p hd l) = "abc"
  else updateLastName(x,tl(l));    // hope this is right

제안 해주세요.


  • 답변 # 1

    어려운 일이 발생했습니다. 깊이 중첩 된 레코드 업데이트.

    레코드에는게터가 있으므로 #fname (#name (#p employee))  이 성을 업데이트하려는 직원임을 알기 위해 확인중인 필드를 가져옵니다. 그러나 레코드는세터에 해당하는 것을 부여하지 않으므로이를 설정해야합니다. 궁금한 점이 있다면렌즈(Haskell)가이 문제를 해결하는 일반적인 방법이지만 표준 ML에 대한 렌즈 구현은 모르겠습니다.

    계속해서 list 를 제거하겠습니다  당신의 employee 에 참여  유형;아마 employee list 를 원할 것입니다  직원이 여러 사람이라고 말하지 않고 여러 직원을 모델링하려는 경우

    type person_name = { fname:string, lname:string, mname:string }
    type person_bio = { age:real, gender:string, name:person_name, status:string }
    type employee = { p:person_bio, payrate:real, whours:real }
    val name1 = { fname = "John", lname = "Doe", mname = "W." } : person_name
    val bio1 = { age = 42.0, gender = "M", name = name1, status = "?" } : person_bio
    val my_employee1 = { p = bio1, payrate = 1000.0, whours = 37.0 } : employee
    val name2 = { fname = "Freddy", lname = "Mercury", mname = "X." } : person_name
    val bio2 = { age = 45.0, gender = "M", name = name2, status = "?" } : person_bio
    val my_employee2 = { p = bio2, payrate = 2000.0, whours = 37.0 } : employee
    val my_employees = [ my_employee1, my_employee2 ] : employee list
    
    

    세터(렌즈를 사용하여 자동으로 파생 할 수있는 것),

    fun setP (p : person_bio, e : employee) =
        { p = p
        , payrate = #payrate e
        , whours = #whours e } : employee
    fun setName (name : person_name, pb : person_bio) =
        { age = #age pb
        , gender = #gender pb
        , name = name
        , status = #status pb } : person_bio
    fun setLname (lname, pn : person_name) =
        { fname = #fname pn
        , lname = lname
        , mname = #mname pn } : person_name
    
    

    예 : 처럼 :

    - setP (setName (setLname ("Johnson", #name (#p my_employee1)), #p my_employee1), my_employee1)
    > val it =
        {p =
               {age = 42.0, gender = "M",
                name = {fname = "John", lname = "Johnson", mname = "W."},
                status = "?"}, payrate = 1000.0, whours = 37.0} :
          {p :
             {age : real, gender : string,
              name : {fname : string, lname : string, mname : string},
              status : string}, payrate : real, whours : real}
    
    

    가독성을 높이기 위해 그 줄을 조금씩 나눌 수도 있습니다 :

    fun updateLname (fname, lname, employees) =
        let fun update employee =
                if #fname (#name (#p employee)) = fname
                then let val new_name = setLname (lname, #name (#p employee))
                         val new_bio = setName (new_name, #p employee)
                         val new_employee = setP (new_bio, employee)
                     in new_employee end
                else employee
        in List.map update employees
        end
    
    

    시도 :

    - updateLname ("Freddy", "Johnson", my_employees);
    > val it =
        [{p = ... {fname = "John", lname = "Doe", mname = "W."}, ... },
         {p = ... {fname = "Freddy", lname = "Johnson", mname = "X."}, ... }]
    - updateLname ("John", "Johnson", my_employees);
    > val it =
        [{p = ... {fname = "John", lname = "Johnson", mname = "W."}, ... },
         {p = ... {fname = "Freddy", lname = "Mercury", mname = "X."}, ... }]
    
    

  • 답변 # 2

    상황에 따라 여기에 참조가 적합 할 수 있습니다.

    값을 변경해야 할 경우이를 참조로 지정할 수 있습니다.

    type person_name = {fname:string, lname:string ref, mname:string}
    type person_bio = {age:real, gender:string, name:person_name, status:string}
    fun change_lname(new_lname: string, bio: person_bio) = (#lname (#name bio)) := new_lname
    val p1 = ...
    print !(#lname (#name p1)) ==> LastName1
    change_lname("LastName2", p1)
    print !(#lname (#name p1)) ==> LastName2
    
    

    레코드에서 데이터를 많이 수정하려는 경우, 하나의 값을 변경해야 할 때마다 프로그램이 메모리를 다시 쓰지 않도록 참조하는 것이 좋습니다. 이것을 최적화 할 수 있습니다). 또한 레코드 서명이 변경되면 세터 기능을 다시 작성하지 않아도됩니다. 단점은 참조를 사용하여 프로그램에 복잡성을 도입한다는 것입니다.

    예를 들어, 위 코드에서 p1의 성을 수정하지 않고 p1과 사본 (함수로 전달)이 모두 같은 문자열을 가리키고 함수에서 해당 문자열을 수정합니다. 실제로 어느 레코드에서든 데이터를 변경하는 시점은 없으며 레코드가 가리키는 데이터 만 변경합니다. 미묘한 차이이며이 예제에서는 실제로 차이가 없지만 디버그하기 어려운 이상한 버그가 발생할 수 있습니다.

관련 자료

  • 이전 angular - 생산시 Identity Server 빈 쿠키
  • 다음 JQuery JQGrid 로컬 데이터로드 문제