2010-06-03 13 views
4

필자가 볼 수있는 한, Scheme을 사용한 함수 프로그래밍에서 iterting 구문을 가르치기위한 일반적인 (그리고 최선의 의견으로는) 순서는 재귀를 먼저 가르치고지도, 축소 및 모든 SRFI-1 절차와 같은 것으로 들어갈 수 있습니다. 재귀를 사용하면 학생은 반복하기에 필요한 모든 것을 갖기 때문에 (아마도 SRFI-1을 원한다면 모든 SRFI-1을 다시 작성하기 때문에) 아마 같을 것입니다.재귀 이전에지도/축소/학습을 배우거나 경험 한 경험이 있습니까?

이제 반대 접근법이 시도 된 적이 있는지 궁금합니다. SRFI-1에서 몇 가지 절차를 사용하십시오. 예를 들어 함수를 추정하는 데 충분하지 않은 경우에만 재귀를 사용하십시오. 내 생각 엔 그 결과가 좋지 않다는 것이지만,이 접근법에 대한 과거 경험에 대해 알고 싶습니다.

물론 이것은 Scheme에만 국한되지 않습니다. 질문은 모든 기능적 언어에도 유효합니다.

Dave Touretsky의 COMMON LISP: A Gentle Introduction to Symbolic Computation은 "응용 프로그래밍"(연결자 사용)을 가르치는 한 책이지만 Common Lisp 서적이므로 그 전에 반드시 반복적 인 반복을 가르 칠 수 있습니다.

+0

예를 들면 다음과 같이 할 수 있습니다. MAP 및 REMOVE,하지만 재귀없이 효과적으로 REDUCE를 보여줄 수 있습니까? –

+0

@sgm : 그냥 stuednts에게 * 사용하는 방법 * 줄이기, 그것을 implmenet하는 방법이 아니라. – Jay

답변

6

지식의 기본 블록으로 시작하는 IMO가 더 나은 다음 결과를 파생시킵니다. 이것은 수학에서 무엇을하는지, 즉 승산 전에 지수화를 도입하지 않으며, 덧셈 전에 곱셈을 유도하지 않는다. 왜냐하면 전자의 경우 각각 후자로부터 유도되기 때문이다. 나는 어떤 강사가 다른 방향으로 가고있는 것을 보았습니다. 그리고 저는 여러분이 기초에서 결과로 갈 때와 같이 성공하지 못했다고 생각합니다. 또한 고급 주제를 늦추면 학생들은 이미 가지고있는 지식을 사용하여 이러한 결과를 유도 할 수있는 정신적 인 어려움을 겪게됩니다.

+1

그들은 곱하기 전에 지수화를 도입하지 않습니다 -하지만 Peano의 공리보다 먼저 덧셈을 설명합니다. (그리고 그 질문에 훨씬 더 비유합니다.) –

+0

여러 수준의 추상화에 대해 이야기 할 때 비유가 정확하다고 생각합니다. 동일한 수준의 추상화에서, 제 의견은 당신이 상향식으로 가야한다는 것입니다. – AraK

+0

그래서 문법 학교에서 Peano 공리를 가르치겠습니까? 좋은 결과 내길 바랄 게! –

2

나는이 교훈을 교훈으로 사용하는 것을 본 적이 없으며, 나는 당신과 마찬가지로 그것을 발견했습니다. 적어도 일부 프로그래머는 "기능 프로그래밍"이 독점적으로 "마법"연결자의 응용 프로그램이라고 생각하고 필요한 조합이 존재하지 않을 때 손실이 있다는 것을 보여주는 StackOverflow에 대한 몇 가지 질문이 있습니다. map3만큼 간단합니다.

이 편견을 고려하여 학생들은 소개 전에 개를 직접 쓸 수 있음을 확인했습니다.

2

재귀가 발생하기 전에 map/reduce를 도입하는 것이 좋습니다. (단, 고전 SICP 먼저 재귀를 소개하고지도를 구현/목록과 재귀를 기반으로 줄일 수 있습니다.이 아래에서 위로 접근 방식에서 건물 추상화입니다. 그 emphises이 추상화. 아직도) 여기

가 sum-입니다 의 제곱의 예는 당신이 F 번호/ML을 사용하여 공유 할 수 있습니다 : 첫 번째는 너무 많은 세부 사항을 표현하면서

let sumOfSqrs1 lst = 
    let rec sum lst acc = 
     match lst with 
      | x::xs -> sum xs (acc + x * x) 
      | [] -> acc 
    sum lst 0 

let sumOfSqr2 lst = 
    let sqr x = x * x 
    lst |> List.map sqr |> List.sum 

두 번째 방법은,이 합계의 제곱 문제를 할 수있는 더 추상적 인 방법입니다. 함수형 프로그래밍의 장점은 더 나은 추상화입니다. List 라이브러리를 사용하는 두 번째 프로그램은 for 루프를 추상화 할 수 있다는 개념을 표현합니다.

학생이 List.*으로 게임을 시작하면이 기능들이 어떻게 구현되는지 알고 싶어합니다. 그 당시 재귀로 돌아갈 수있었습니다. 이것은 일종의 하향식 교수법입니다.

+2

비교는 "더 추상적이거나 너무 자세하게"멈추지 않습니다. 두 번째 구현은 또한 즉시 버려지는 전체 목록을 할당합니다. 학생들이 그렇게하도록 가르치는 것이 걱정됩니다. 최고의 학생들은 우아하게 일을 할 수 없기 때문에 가르치는 언어를 알아 채고 경멸합니다. 다른 사람들은 눈치 채지 않고 자신이하는 일에 대해 생각조차하지 않고 구조를 복제하는 것이 괜찮다는 것을 잠정적으로 배웁니다. –

+0

@Pascal. 좋은 지적. 그러나 제 생각에는 모든 지식에는 여러면이 있습니다. 'List.map'의 경우, 처음에는 학생들에게 소개되어지고, 상위 레벨 추상으로 사용할 수 있습니다. 나중에 모든 세부 사항을 가르치면 예제의 사용법으로 되돌아 가서 비효율 문제를 알 수 있습니다. 한 번의 방문으로 철저히 한 가지를 배우는 것은 매우 어렵습니다. –

3

"반복하는 데 필요한 모든 것이 재귀가 있습니다."라는 말에는 근본적으로 결함이 있습니다.사실 (재귀 적) 함수를 작성하는 방법을 알면 무엇이든 할 수 있지만, 학생의 경우 더 나은 것은입니까? 당신이 그것에 대해 생각할 때, 당신은 기계 언어를 아는 경우에 당신이 필요로하는 모든 것을 가지거나, 당신에게 전선과 CPU를 줄 경우 더 극단적 인 지점을 만들 수 있습니다.

네, 너무 과장되었지만 사람들이 가르치는 방식과 관련 될 수 있습니다. 모든 언어를 가져 와서 불필요한 구문을 제거하십시오. Scheme과 같은 기능적 언어에서 극단적으로 그렇게하면 람다 미적분 (또는 비슷한 것)이 남게됩니다. 다시 말하면 필요한 모든 것입니다. 하지만 분명히 더 많은 영역을 다루기 전에 초보자를 그 냄비에 던져서는 안됩니다.

는이 제도에 구현 등의 목록의 차이를 고려,보다 구체적인 관점에 넣고합니다. 쌍으로 구현 된 방법에 대해 알지 못하는 경우에도 목록만으로 많은 작업을 수행 할 수 있습니다. 사실, 학생들에게 두 번째 논점으로 적절한 목록을 요구하는 제한된 형태의 cons을 제공하면 목록이 어떻게 사용되는지에 대한 세부 사항으로 넘어 가기 전에 일관성있게 쉽게 이해할 수있는 개념을 도입하여 도움을 줄 것입니다. 구현. 이 물건을 가르쳐 본 경험이 있다면, cons을 사용하여 많은 사람들과 절망적으로 혼동하는 많은 학생들과 마주 치고 있다는 것을 확신합니다. 그 반대로는 append을 원합니다. 둘 다 필요로하는 문제는 초보자에게는 매우 어려울 수 있으며 전 세계의 모든 상자 + 포인터 다이어그램은 도움이되지 않습니다.

그래서, 실제 제안을주고, 당신이 HtDP 봐이 좋습니다 것들 중 하나이 책은 확인하고, 매우 신중하게 프로그래밍 점차적으로 학생을 노출시키는하고 있는지를 그 정신 사진에서 모든 단계는 학생이 그 시점에서 알고있는 것과 일치합니다.

+2

HtDP는 목록을 작성하기 전에 위치에 대한 사용자 지정 데이터 형식을 소개하지만 연결자 앞에 재귀를 가르칩니다. –

+1

글쎄, 나는 "더 기본적인"= "배터가 더 일찍 가르쳤다"는 맹목적인 믿음에 대해서 실제 맵 대 재귀에 대한 의견을 표현하지 않았다. 어쨌든, HtDP는 매우 체계적으로 재귀를 가르친다. 사실상 모든 책과는 달리 구조 재귀가 훨씬 이해하기 쉽기 때문에 '사실'로 시작하지 않는다. (숫자에 대한 재귀도 구조적이지만 매우 명확하지 않은 구조입니다.) –

1

나는 이것이 나쁜 생각이라고 생각합니다.
재귀는 이해하기 쉽고 사용하기가 더 어려운 프로그래밍의 가장 어려운 기본 과목 중 하나입니다. 이것을 배우는 유일한 방법은 그것을하는 것입니다.
학생들에게 멋지게 추상화 된 고차 함수가 전달되면이 재귀를 통해 상위 순서 함수를 사용하게됩니다. 그런 다음 고차 함수를 스스로 작성해야 할 때, 그들은 단서가 없으며 선생님이 코드를 실제로 작성해야합니다.
누군가가 언급했듯이 사람들에게 이 실제로 인 사람들이 자신의 필요에 맞게 사용자 정의하기를 원한다면 주제를 배워야합니다.

-1

당신이 실제로 가르치고 배우고 싶은 "재귀"는 궁극적으로 재귀가 아니라 재귀이지만 루프입니다.

그래서 실제 재귀를 가르치거나 배우고 (실용적이지 않기 때문에 아무도 실생활에서 사용하지 않습니다), 왜 쓸모 없는지 가르치고, 꼬리 재귀를 가르치고, 왜 그들이 그렇지 않은지를 가르칩니다. 재귀.

내가 가장 좋은 방법 인 것 같습니다. 학습하는 경우 고차 함수를 너무 많이 사용하기 전에이 모든 작업을 수행하십시오. 가르치고 있다면 루프를 대체하는 방법을 보여줍니다 (그리고 나중에 꼬리 재귀를 가르 칠 때 루핑이 실제로 숨겨져 있지만 어떻게 계속 남아 있는지 이해하게 될 것입니다).

+2

"루프"는 프로그래머가 꼬리 호출 최적화를 수동으로 적용한 재귀 함수입니다. 나는 우리가 * 장려하기를 원하지 않는다고 생각한다. 컴파일러를 가지고있는 것들을 사소한 난독 화 최적화에 적용하지 않겠는가? 어쨌든 일반적인 재귀는 더 강력합니다. 따라서 재귀를 사용하는 대신 현명하게 재귀 호출을 사용하여 꼬리 재귀를 과도하게 사용하는 사람들이 자신의 의사 호출 스택을 만들어 휠을 재발 명하게 만듭니다. –

+0

이론적으로 보면 "루프"를 "재귀 함수"로 생각할 수 있습니다. 그러나 나는 그것이 기계어로 어떻게 변환되는지에 대해 이야기하고 있으며 꼬리 재귀는 JMP로 변환되지만 C의 "for"루프는 어셈블리에서 함수 호출로 변환되지 않는다. 따라서 루프가 단지 재귀 함수라는 것을 말할 때 실제로 POV가 아닌 POV에서 볼 수 있어야합니다. 일반 재귀는 스택 오버플로를 발생시킵니다. 그것은 누군가가 사용해야하는 것이 아닙니다. – PeterM

+1

컴파일러가 뱉어내는 것은 구현에 따라 다릅니다. C 컴파일러가 무언가를 위해 정말 끔찍한 바이너리 코드를 생성한다면 더 나은 컴파일러를 찾거나 그 결함을 해결할 수 있습니다. 일반적인 재귀는 많은 알고리즘을 표현하는 가장 자연스러운 방법이며, 힙에 두 번째 스택을 작성하여 바퀴를 다시 만들지 않고 사람들이 사용해야하는 것입니다. 사용하는 도구의 한계가 생각하는 생각을 제한하지 않도록하십시오! –

0

프로그래밍 할 때 많은 사람들이 명령형을 '모방'하고 반복문을 닮은 것을 필요로하지 않고지도를 필요로하거나 접히거나 줄일 필요가있을 때 재귀를 사용하여 루프를 모방하려고합니다.

대부분의 기능을하는 프로그래머는 명령형을 모방하지 말아야한다는 데 동의하지만, 재귀는 전혀 배우지 않아야한다고 생각하지만 자연스럽고 자명 한 개발을해야한다고 생각합니다. 선언적 프로그래밍에서는 종종 다양합니다. 포인트는 함수가 그 자체로 정의된다는 것을 분명히합니다. 재귀는 '루핑'으로 보지 말고 '자체적으로 함수를 정의'해야합니다.

지도 그러나 반복적으로 똑같은 것을 반복합니다. 사람들이 루프를 시뮬레이트하기 위해 (꼬리) 재귀를 사용하는 경우 함수 스타일로지도를 사용해야합니다.

관련 문제