Ракетка, пишущая функция, которая находит n-й элемент в списке - PullRequest
0 голосов
/ 14 мая 2018

Чтобы понять функциональное программирование, помогите мне написать функцию, которая выводит n-й элемент списка,

Допустимая команда:

define  lambda  cond  else  empty  empty?  first  rest  cons  list

list?  =  equal?  and  or  not  +  -  *  /  <  <=  >  >=

Пример вывода:

(четвертый элемент '(abcde)) => d

(четвертый элемент' (x (yz) whj)) => h

(четвертый элемент '((ab) (cd) (ef) (gh) (ij))) => (список 'g' h)
или '(gh)

(четвертый элемент' (abc))=> пусто

Я мог бы написать это на python, но я не являюсь семьей с синтаксисом ракеток,

def element(lst, x=0):
  counter = x;
  if (counter >= 3):
    return lst[0]
  else:
    return element(lst[1:],x+1)

a = [1,2,3,4,5,6]
print(element(a))

Вывод 4 Сравнение с кодом выше в python,Что такое эквивалентное поведение в функции, создающей локальную переменную counterЧто такое "ключевое слово" для возврата

Ответы [ 3 ]

0 голосов
/ 14 мая 2018

Похоже, вы придумали собственный ответ. Хорошо сделано! Я бы порекомендовал более общую nth процедуру, которая принимает counter в качестве аргумента. Это позволяет получить любой элемент в списке ввода

(define (nth lst counter)
  (cond ((null? lst) (error 'nth "index out of bounds"))
        ((= counter 0) (first lst))
        (else (nth (rest lst) (- counter 1)))))

Теперь, если вам нужна процедура, которая возвращает только 4-й элемент, мы создадим новую процедуру, которая специализируется на обобщенном nth

(define (fourth-element lst)
  (nth lst 3))

Вот и все. Теперь мы проверяем их с вашими входами

(define a `(1 2 3 (4 5) 7))
(define b `(1 2 3))
(define c `((a b)(c d)(e f)(g h)(i j)))
(define d `(a b c))

(fourth-element a) ; '(4 5)
(fourth-element b) ; nth: index out of bounds
(fourth-element c) ; '(g h)
(fourth-element d) ; nth: index out of bounds

Обратите внимание, что когда счетчик выходит за границы, я решил повысить error вместо того, чтобы возвращать значение ("empty"), как ваша программа. Возвращение значения делает невозможным узнать, действительно ли вы нашли значение в списке или было возвращено значение по умолчанию. В приведенном ниже примере обратите внимание, что ваша процедура не может различить два входа

(define d `(a b c))
(define e `(a b c ,"empty"))

; your implementation
(fourth-element e) ; "empty" 
(fourth-element d) ; "empty"

; my implementation
(fourth-element e) ; "empty" 
(fourth-element d) ; error: nth: index out of bounds

Если вы не хотите выдавать ошибку, есть другой способ, которым мы можем кодировать nth. Вместо возврата n-го элемента мы можем вернуть n-ную пару , в голове которой находится рассматриваемый элемент.

Ниже nth всегда возвращает список. Если список пуст, элемент не найден. В противном случае n-й элемент - это элемент first в результате.

(define (nth lst counter)
  (cond ((null? lst) '())
        ((= counter 0) lst)
        (else (nth (rest lst) (- counter 1)))))

(define (fourth-element lst)
  (nth lst 3))

(define a `(1 2 3 (4 5) 7))
(define b `(1 2 3))
(define c `((a b)(c d)(e f)(g h)(i j)))
(define d `(a b c))
(define e `(a b c ,"empty"))

(fourth-element a) ; '((4 5) 7)
(fourth-element b) ; '()
(fourth-element c) ; '((g h) (i j))
(fourth-element d) ; '()
(fourth-element e) ; '("empty")

Надеюсь, это заставит вас задуматься о domain (тип ввода процедуры) и codomain (тип вывода процедуры).

В общем, вы хотите разработать процедуры, которые имеют естественные описания, такие как:

  • "nth берет список и число и всегда возвращает список" (лучший)
  • "nth берет список и число и возвращает элемент списка или вызывает исключение, если элемент не найден" (хорошо, но теперь вы должны обрабатывать ошибки)

Избегайте таких процедур, как

  • "nth принимает список и число и возвращает элемент списка или строковый литерал "empty", если элемент не найден" * (неясный кодомен)

Размышляя о домене и кодомене вашей процедуры, вы понимаете, как будет работать ваша функция, будучи встроенной в различные части вашей программы. Использование многих процедур с плохо определенными доменами приводит к гибельному коду спагетти. И наоборот, четко определенные процедуры могут быть собраны как строительные блоки с небольшим (или без) необходимым кодом клея.

0 голосов
/ 15 мая 2018

Вот как написать это на Python:

def nth(lst, idx=0):
  if (len(lst) == 0):
    return "empty"
  elif (idx == 0):
    return lst[0]
  else:
    return nth(lst[1:], idx - 1)

nth([1,2,3], 1)
# ==> 2

def fourth-element(lst):
  return nth(lst, 4)

То же в схеме / ракетке:

(define (nth lst idx)
  (cond ((empty? lst) empty)  ; more effiecent than (= (length lst) 0)
        ((= idx 0) (first lst))
        (else (nth (rest lst) (- idx 1))))

(nth '(1 2 3) 1)
; ==> 2

(define (fourth-element lst)
  (nth lst 4))

Нет ключевого слова для return. Каждая форма возвращает последний оцененный код:

(if (< 4 x)
    (bar x)
    (begin 
      (display "print this")
      (foo x)))

Этот if возвращает либо результат (bar x), либо выводит «print this», а затем возвращает (foo x). Причина в том, что для двух результатов if они являются хвостовыми выражениями.

(define (test x)
  (+ x 5)
  (- x 3))

Эта функция имеет два выражения. Первый - это мертвый код, поскольку он не имеет побочного эффекта и не является хвостовым выражением, но (- x 3) - это то, что возвращает эта функция.

(define (test x y)
  (define xs (square x))
  (define ys (square y))
  (sqrt (+ xs ys)))

Это имеет 3 выражения. Первые два имеют побочные эффекты, которые связывают две локальные переменные, в то время как третья использует это для вычисления возвращаемого значения.

0 голосов
/ 14 мая 2018
(define a `(1 2 3 (4 5) 7))
(define b `(1 2 3))
(define c `((a b)(c d)(e f)(g h)(i j)))
(define d `(a b c))

(define (my-lst-ref lst counter)
  (cond[(>= counter 3) (first lst)]
       [else (my-lst-ref (rest lst)(+ counter 1))]
       )
  )

(define (fourth-element lst)
  (cond[(>= (list-length lst) 4) (my-lst-ref lst 0)]
       [else "empty"]))

(fourth-element a)
(fourth-element c)
(fourth-element d)

Выход:

(список 4 5)
(список «г» ч)
"Пустой"

...