LINUX.ORG.RU

простой пример на scheme


0

0

Имеется такая задача: написать программу вычисления
значения функции
  { a * (i ^ 2) : если i < 3
f { a * (i ^ 3) + b * i : если 3 <= i <= 7
  { i + 10 * (i ^ 4) : если i > 7
для i [2; 8], изменяется с шагом 1.0

Почитав немного всяческих док, написал вот это:

(define f-funct
 (lambda (a b i)
  (if (< i 3) (* a (* i i))
   (if (< i 8) (+ (* a (* i i i)) (* b i))
    (+ i (* 10 (* i i i i)))))))

(define ep-loop
 (lambda (a b i)
  (if (and (> i 1) (< i 9))
   (and (print "f(" a ", " b ", " i ") : " (f-funct a b i))
    (ep-loop a b (+ i 1))))))

(define (main argv)
;(let ((a (if (null? (cdr  argv)) -0.50 (string->real (cadr  argv))))
;      (b (if (null? (cddr argv))  0.70 (string->real (caddr argv)))))
 (let ((a -0.50)
       (b  0.70))
  (ep-loop a b 2)))

Вроде как работает, но хотелось бы узнать где я не прав и
насколько мое C-шное прошлое повлияло на результат ;-)
Покажите, если не трудно, как _правильно_ подобные задачи
решать на scheme/lisp.
anonymous

Ну от того, что ты написал lambda, твоя программа не стала "функциональной" :) Потом возведение в степень надо в отдельную функцию, с оптимальном алгоритмом(там используется принцип "разделяй и властвуй").

anonymous
()
Ответ на: комментарий от anonymous

> Ну от того, что ты написал lambda, твоя программа не стала "функциональной"
Вот и я про то же :-) В этом и есть суть вопроса - покажите как эту задачу решить функционально.

anonymous
()

В очередной раз порадовало обилие скобочек :) У меня вопрос в догонку к гуру scheme/lisp: есть ли какие-нибудь правила/методики обеспечения читабельности кода? Как это вообще должно выглядеть.

KIV
()
Ответ на: комментарий от KIV

Вообще-то этот код вполне читабелен, ну можно добавиьт пару переносов для полной красоты:)

anonymous
()

ИМХО с cond будет читаться первая луче, типо 

(define f-funct (lambda (a b i)
  (cond 
    ((< i 3) (* a i i))
    ((> i 7) (+ i (* 10 i i i i)))
    (t (+ (* a i i i) (* b i))))))

bugmaker ★★★★☆
()

Да нормальный, код. Но, 1. совет про cond нужно учесть; 2. желательно разделять функциональные и императивные части (если это возможно), т. е. сначала вычисли список значений, а затем выведи их отдельной функцией (читабельность повысится); 3. совет с возведением в степень ерундовый - у тебя степени до четвертой, так что смысла нет (разве что заменить (* i i i i) на (sqr (sqr i)); 4. в scheme есть возможность для последовательности вычислений (вместо and у тебя);

// satanic-mechanic

anonymous
()
Ответ на: комментарий от anonymous

Да нормальный, код. Но,
1. совет про cond нужно учесть;
2. желательно разделять функциональные и императивные части (если это
   возможно), т. е. сначала вычисли список значений, а затем выведи их
   отдельной функцией (читабельность повысится);
3. совет с возведением в степень ерундовый - у тебя степени до
   четвертой, так что смысла нет (разве что заменить (* i i i i) на
   (sqr (sqr i));
4. в scheme есть возможность для последовательности вычислений (вместо
   and у тебя);

// satanic-mechanic

anonymous
()
Ответ на: комментарий от anonymous

>Вообще-то этот код вполне читабелен

Неверное практика нужна чтоб слету читать... просто не приятно выглядит количество скобочек в конце блока %), в примере 7 скобок!!! Когда проект больший, наверное утонешь в них :)

>ну можно добавиьт пару переносов для полной красоты:

Можно? Не нужно? И где :)

KIV
()
Ответ на: комментарий от KIV

> Неверное практика нужна чтоб слету читать...

А есть язык, где такая практика ВООБЩЕ не нужна? ;)

> в примере 7 скобок!!! Когда проект больший, наверное утонешь в них :)

Да просто не замечаешь :)

yyk ★★★★★
()

1. Лямбду бы лучше убрать, имхо лучше смотриться (define (f-funct a b i)...

2. Cond уже посоветовали

3. Expt таки лучше заюзать, и не написать самому а взять из либы.

4. Вместо ep-loop написать две функции. Одна генерирует список чисел от A до B с интревалом i: (range 1 10 1), потом взять из либы или 
написать макрос for-each и написать:

(for-each (i (range 1 10 1))
  (print "f(" a ", " b ", " i ") : " (f-funct a b i)))

или вместо for-each заюзать map.

(map (lambda (x) (print "f(" a ", " b ", " i ") : " (f-funct a b i))
     (range 1 10 1))

более функционально но менее читабельно...

CrazyPit ★★★
()
Ответ на: комментарий от KIV

> Когда проект больший, наверное утонешь в них :)

Гы. Величина проекта никак не влияет на количество скобок, только величина функции. Вот сейчас грипаю реальный проект на лиспе, больше 10 скобочек закрывающихся нет:)) Да и от 6 до 10 не так много -> более 6 закрывающихся скобочек 21 на проект в 2,5K строк.

Да и лисперы в основном делают скобки очень тусклыми, поэтому на них внимание не отвлекается.

CrazyPit ★★★
()

Спасибо всем за комменты. Результат:

(define f-funct (lambda (a b i)
  (cond ((< i 3) (* a (expt i 2)))
        ((> i 7) (+ i (* 10 (expt i 4))))
        (else (+ (* a (expt i 3)) (* b i))))))

(define mk-seqn (lambda (f t s)
  (if (> f t) '() (cons f (mk-seqn (+ f s) t s)))))

(define (main argv)
 (let ((a -0.50)
       (b  0.70))
 (map (lambda (i) (print "f(" a ", " b ", " i ") : " (f-funct a b i)))
  (mk-seqn 2 8 1))))

Это была одна из задач по информатике, 1 курс универа.
В ответ на вопрос "Можно ли обойтись без этого паскаля"
препод сказал что-то типа "пишите на чем вам хочется,
я ASM прошел мне теперь все пох". Посмотрим что он сегодня скажет, хехе

anonymous
()
Ответ на: комментарий от bugmaker

>А ты скобки не читай, код читай.

А скобки не код? Вот это новость ;) Я думал перестановка пары скобочек повлечет за собой ошибку логики, и вдобавок эта ошибка может быть не обнаружена автоматикой (быть неявной). Я ошибаюсь?

KIV
()
Ответ на: комментарий от anonymous

>Это была одна из задач по информатике, 1 курс универа. В ответ на вопрос "Можно ли обойтись без этого паскаля" препод сказал что-то типа "пишите на чем вам хочется, я ASM прошел мне теперь все пох". Посмотрим что он сегодня скажет, хехе

Помню в универе одногрупница одна любила на lispe в строчку все присать (именно писать а не просто подлянку делать убирая переводы строк) - благо лабы были достаточно небольшие. Препод вешался, хотя предмет знал хорошо :)

KIV
()
Ответ на: комментарий от anonymous

Вот попробовал на С подобном эту задачку. Все таки выбор языка решает :)

ffunct(a,b,i,)
{
if(i<3) return a*i*i;
if(i>7) return i+(10*i*i*i*i);
return (a*i*i*i)+(b*i);
}

Сорри за оффтопик, просто интересное сравнение.

KIV
()
Ответ на: комментарий от yyk

>А есть язык, где такая практика ВООБЩЕ не нужна? ;)

Может и есть, но я пока не встречал :)

>Да просто не замечаешь :)

Вот это уже ахтунг! :) А как часто бывают ошибки вызванные этим? И насколько долго они отлавливаются?

KIV
()
Ответ на: комментарий от KIV

> Помню в универе одногрупница одна любила на lispe в строчку все присать (именно писать а не просто подлянку делать убирая переводы строк) - благо лабы были достаточно небольшие. Препод вешался, хотя предмет знал хорошо :)

А про pretty-printer препод не знал? ;)

yyk ★★★★★
()
Ответ на: комментарий от KIV

> Вот это уже ахтунг! :) А как часто бывают ошибки вызванные этим? И насколько долго они отлавливаются?

;) Я хотел сказать, что ты их НИКОГДА не считаешь... Редактор тебе просто пару/лишние подсвечивает - этого достаточного для того, чтобы не обращать на скобочки внимание как на отдельную сущность :)

yyk ★★★★★
()
Ответ на: комментарий от yyk

>> Помню в универе одногрупница одна любила на lispe в строчку все присать (именно писать а не просто подлянку делать убирая переводы строк) - благо лабы были достаточно небольшие. Препод вешался, хотя предмет знал хорошо :)

>А про pretty-printer препод не знал? ;)

Может не знал, может ударить в грязь лицом боялся - "она же пишет так!" %()

:)

KIV
()
Ответ на: комментарий от KIV

ffunct(a,b,i,)
{
if(i<3) return a*i*i;
if(i>7) return i+(10*i*i*i*i);
return (a*i*i*i)+(b*i);
}

И чем интереснее решает? то что в лиспе на 8 лексем меньше? Ну это не 
суть важно.

CrazyPit ★★★
()
Ответ на: комментарий от KIV

> Помню в универе одногрупница одна любила на lispe в строчку все присать (именно писать а не просто подлянку делать убирая переводы строк) - благо лабы были достаточно небольшие. Препод вешался, хотя предмет знал хорошо :)

Ты ведь в ПГУ учился? а где у нас на лиспе лабы делают?

CrazyPit ★★★
()
Ответ на: комментарий от anonymous

> (define f-funct (lambda (a b i) (cond ((< i 3) (* a (expt i 2))) ((> i 7) (+ i (* 10 (expt i 4)))) (else (+ (* a (expt i 3)) (* b i))))))

Нет, всё-таки скажи зачем ты пишешь (define func (a ... вместо (define (func a ...) ?

> Посмотрим что он сегодня скажет, хехе

Помню я тоже лабы на лиспе здавал в прошлом году, ничего преподша всё просекла, хоть в лиспе и не шарила.

CrazyPit ★★★
()
Ответ на: комментарий от CrazyPit

Далеко не все пользуются этим сахарком, есть пуристы, которые вообще за искоренение (define (foo bar) ...

grob ★★★★★
()
Ответ на: комментарий от CrazyPit

>Ты ведь в ПГУ учился?

Ага.

>а где у нас на лиспе лабы делают?

Как это где :( )! На ФВТ, специальность 220400 (была, сейас как-то по другому). А что сейчас уже этому не учат?

KIV
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.