2009-08-20 2 views
4

나는 f #을 배워서 어리석은 짓을하고 있습니다. 자유롭게 관련 문서를 가리키며 검색했지만 찾지 못했습니다. Windows 7 (.Net 4.0)에서 Visual Studio 2010 베타를 사용하고 있습니다.f #의 들여 쓰기 문제 (vs2010 beta1)

모든 것이 내 첫 번째 f # 프로젝트에서 잘 진행되고 있습니다. 음 .. 거의 모든 것.

let linterp (x:double) (xvalues:double list) (yvalues:double list) = 
    let num_els = xvalues.Length 
    if x <= xvalues.Head then 
     let result = yvalues.Head 
    elif x >= (List.rev xvalues).Head then 
     let result = (List.rev yvalues).Head 
    else for idx in [0 .. num_els] do 
     if List.nth xvalues idx >= x then 
      let x0 = xvalues.Item idx 
      let y0 = yvalues.Item idx 
      let x1 = xvalues.Item (idx+1) 
      let y1 = yvalues.Item (idx+1) 
      let result = y0 + (y1-y0)/(x1-x0)*(x - x0) 
    result 

을 나는 완전히 내 이해를 회피 오류의 시리즈를 수신하고 : 특히 에서 나는 다음과 같은 코드로, 매우 간단한 선형 보간 기능을 쓰고 있어요. 제 1, 제 2, 제 마지막으로 "하자"에 대한

  • ".이 '하자'가능한 올바른 들여 쓰기에 대한 반환 표현의 오류"

    는 오류 및 경고의 목록입니다.

  • 다음

  • "만약" "불완전한 구조 구조는"가능한 잘못된 압입.이 토큰 위치 (39:10)에서 시작 콘텍스트 오프사이드이다 더욱이 토큰을 압입 또는 표준 포맷 규칙을 사용하여 시도 " 마지막 행 (결과)에 대해 표현식의이 시점 이전에 ".

내가 나에게 알 수없는 어떤 이유로 컴파일러가 첫 번째 목록에 대해 올바르게 추론 할 수 있었다 때문에 유형에 주석을 조금 땀을했다는 것을 추가 할 것입니다,하지만 두 번째의 유형은 항상 추론했다 단위는 또한, 내 원래 버전은 이름 결과를 결합하지 않았다로, 단순히 이것은 "에 대한"에서 오류가 잎에

if x <= xvalues.Head then 
    yvalues.Head 

처럼 또는

else for idx in [0 .. num_els] do 
    if List.nth xvalues idx >= x then 
     let x0 = xvalues.Item idx 
     let y0 = yvalues.Item idx 
     let x1 = xvalues.Item (idx+1) 
     let y1 = yvalues.Item (idx+1) 
     y0 + (y1-y0)/(x1-x0)*(x - x0) 

에, "표현을 반환" 말하다 "이 표현식은 유형 단위를 가지지 만 여기서 double 유형과 함께 사용되며"if "가 잘못 들여 쓰기 될 수 있습니다.

나는 이것에 대한 해결책을 보게 될 때 바보가 될 것이라고 생각하지만, 한 시간 이상 간단한 문제에 매달 렸기 때문에 나는 당신의 도움을 요청하고 있습니다.

미리 감사드립니다.

PS : 나는 탭이 올바르게 도구 -> 옵션에 공백으로 해석되는 것을 확인했습니다 -> ... -> F 번호 -> 탭 메뉴

PPS :이 그래서 내 첫 번째 질문입니다 :-)

+0

나는 부끄러워하지만 코드에 분명히 하나씩 오류가있다. :-) 그건 내가 밤늦게까지 코딩하기에는 너무 오래되었음을 증명한다. idx는 x보다 크거나 같은 첫 번째 항목을 나타 내기 때문에'let x0 = xvalues.Item (idx - 1)'및'let x1 = xvalues.Item idx'를 사용합니다. – Francesco

답변

5

당신의 문제는 무엇인가

let result = yvalues.Head 

같은 것은 완전한 표현하지 않고, 그래서이 if 블록의 가지 중 하나의 몸을 형성 할 수 있다는 것입니다. for ... do 루프가 의미있는 값을 반환하지 않는다는 점을 제외하고는 처음 접근법이 정확했습니다. unit 유형의 유일한 값인 ()을 반환합니다 (컴파일러가 설명하려고 시도 할 때). 이것은 C#과 같은 언어에서 void과 유사합니다. . for 루프 대신에 원하는 값을 가진 식을 사용하는 것이 좋습니다.코드에 대한 가장 작은 변경은 루프에서 필수적으로 설정 한 가변 값을 사용하는 것입니다. 관용적 인 접근법은 List.fold와 같은 내장 함수를 사용하여 목록을 단일 값으로 압축하는 것입니다. 목록의 연속적인 항목에 액세스해야한다는 점 (그리고 xvalue와 yvalues를 동시에 시뮬레이트해야 함)이 복잡해 지므로 List.zip과 Seq.pairwise를 사용해야 할 수도 있습니다. F #에 익숙하지 않은 사람의 선명도를 줄이십시오.

또한 코드를 더 관용적으로 적용 할 수있는 몇 가지 다른 변경 사항이 있습니다. 예를 들어 let x0 = xvalues.Item idx은 더 일반적으로 let x0 = xvalues.[idx]으로 작성됩니다. 그러나 F # 목록은 불변의 링크 된 목록이므로 빠른 임의 액세스를 지원하지 않습니다. 이것이 내장 된 List 연산자를 사용하는 접근 방식을 선호하는 또 다른 이유입니다.

+0

감사합니다. 이제 오류의 의미를 더 잘 이해합니다. 예 : #light 구문을 사용하지 않았 으면 x35 = xvalues.Head이면 을 작성해야합니다. 에 결과 = yvalues.Head를 넣고 "in"은 내가 지역 범위와식이 빠져있다 (필자는 6.7 절에서 f # spec에서 Binding Expressions를 읽었다). 그것은 for ... do 루프가 부작용으로 실행되는 것 같습니다. 맞습니까? 더 많은 관용구 코드에 대한 제안을 보내 주셔서 감사합니다. 나는 아직도 배우기 때문에 나는 아직도 매우 어색하다. 나는 Seq.pairwise로 접근을 시도 할 것이다. – Francesco

5
let linterp x (xvalues:double list) (yvalues:double list) = 
    if x <= xvalues.Head then 
     yvalues.Head 
    elif x >= (List.rev xvalues).Head then 
     (List.rev yvalues).Head 
    else 
     let idx = List.findIndex (fun e -> e >= x) xvalues 
     let x0 = xvalues.Item idx 
     let y0 = yvalues.Item idx 
     let x1 = xvalues.Item (idx+1) 
     let y1 = yvalues.Item (idx+1) 
     y0 + (y1-y0)/(x1-x0)*(x - x0)