Запрос на проверку кода и предложения по улучшению (было: Вопрос о включении функции в список)

Очистка вопроса по запросу acl:

У меня есть следующий код

AddGeometry[scg_, tfg_, geo_] := 

Module[{
i,
georec},

If[StringQ[geo[[2,1]]]&&StringMatchQ[geo[[2,1]],"GE"],   (* DIRTY, BWAH *)
    AddAsChild[scg, tfg, geo],
    (
    i=1;
    While[i<=Length[geo],
        georec=geo[[i]];
        AddGeometry[scg, tfg, georec];
        i++
    ]
    )
]

]

SetAttributes[AddGeometry, HoldAll];

гео_ выглядит так:

{
{4, {"GE", {"CU", {{0, 0, 0}, 4}}}, 5, 2}, 
{7, {"GE", {"CU", {{0, 3, 0}, 1}}}, 5, 2},
{12, {"GE", {"CU", {{0, 5, 0}, 2}}}, 5, 2},
}

Он содержит 1, 2, ... n записей типа {4, {"GE", {"CU", {{0, 0, 0}, 4}}}, 5, 2}.

Код вызова выглядит так

c1 = NewCube[]

( c1 получает значение, подобное {4, {"GE", {"CU", {{0, 0, 0}, 4}}}, 5, 2}) и т. д.

AddGeometry[scg, tfg, c1]

ИЛИ, когда необходимо добавить несколько геометрий:

AddGeometry[scg, tfg, {c1, c2, c3}]

Код выше работает.

Вопрос:

  • Есть ли более чистый способ (с использованием полиморфизма) реализовать это?

От @acl:

AddGeometry[scg_, tfg_, geo_] := 
Module[{
    georec=geo}, 

    AddAsChild[scg, tfg, georec]

] /; MatchQ[geo, {_, {"GE", __}, __}];      

AddGeometry[scg_, tfg_, geo_] := 
Module[{},
    Map[AddGeometry[scg, tfg, #] & ,geo]
]

person nilo de roock    schedule 11.06.2011    source источник
comment
Я не понимаю вопроса. Использование SetAttributes[AddGeometry, {HoldAll, Listable}]; и AddGeometry[scg, tfg, {c1, c2}] дает {AddAsChild[scg, tfg, NewCube[{0, 0, 0}, 4]], AddAsChild[scg, tfg, NewCube[{10, 0, 0}, 4]]}, что кажется правильным. Кроме того, как NewGeometry относится к чему-либо? Простите меня, если я просто туплю.   -  person Mr.Wizard    schedule 11.06.2011
comment
@Mr.Wizard Я (возможно, неправильно) истолковал вопрос как то, что прямая установка атрибута Listable неудовлетворительна по неуказанным причинам. Кажется, что остальная часть реализации (здесь не указана) также важна (см., Например, мою попытку ответа, которая не работает в реальной среде, настроенной ndroock1)   -  person acl    schedule 11.06.2011
comment
если вам не нравится беспорядок {,{GE,},} (мне не нравится), рассмотрите возможность создания структуры с головным geoRec, которая будет хранить записи, и вы могли бы затем используйте AddGeometry[scg, tfg_, geo_geoRec] (или соответствующую структуру /; MatchQ), что менее уродливо. начать новый вопрос, если вы хотите для этого.   -  person acl    schedule 12.06.2011
comment
например, вы можете представить {4, {GE, {CU, {{0, 0, 0}, 4}}}, 5, 2} как georec[4, GE, CU, {0, 0, 0}, 4, 5, 2], а затем, если (скажем) {0,0,0} является какой-то точкой, определить getPoint[el_georec]:=georec[[4]] и так далее. это защитит ваши программы от взлома каждый раз, когда вы меняете свои структуры данных (конечно, это стандартно для других языков, но в математике это может быть не так очевидно, что вы можете сделать это таким образом)   -  person acl    schedule 12.06.2011
comment
@acl, что ты имеешь против grpat = {_, {"GE", __}, __}, функции, производительности, эстетики и прочего? Я тоже подумал о вашем предложении, но я не хотел требовать, чтобы ОП изменил свой формат данных.   -  person Mr.Wizard    schedule 13.06.2011
comment
@ Мистер, в основном надежность. Если бы я писал это сам, я бы сделал это так, как я описал, и написал констрикторы, геттеры и сеттеры, чтобы я мог изменять структуры по своему вкусу, не беспокоясь о том, чтобы сломать что-либо вне этого (т.е. я бы построил интерфейс). Но все мы делаем что-то по-разному (и я думаю, что Леонид сейчас внезапно появится и сотворит какое-нибудь волшебство, которое оставит остальных из нас слабыми)   -  person acl    schedule 13.06.2011
comment
@acl, это действительные точки. Я думаю, я не решаюсь сказать кому-то изменить свой код/методы вне непосредственного вопроса, если только им это не нужно. Я не уверен, почему. Опять же, я мог бы учиться у Леонида, поскольку ему удается демонстрировать превосходные методы, не говоря ОП, что вы делаете это неправильно.   -  person Mr.Wizard    schedule 13.06.2011
comment
@Мистер. Конечно, я не говорю ndroock1 делать это по-моему. Я просто догадался, что он нашел уродливым, и предложил возможный способ скрыть уродство (вероятно, ценой производительности)   -  person acl    schedule 13.06.2011
comment
@acl - вчерашнее упражнение было полезным. Прощай, код, вернемся к чертежной доске. Я очень ценю помощь этого форума.   -  person nilo de roock    schedule 13.06.2011


Ответы (2)


В ответ на обновленный вопрос, как насчет

 ClearAll[AddGeometry];
 SetAttributes[AddGeometry, HoldAll];

 AddGeometry[scg_, tfg_, geo_] := Module[{}, AddAsChild[scg, tfg, geo]] /; MatchQ[geo, {_, {"GE", __}, __}];

 AddGeometry[scg_, tfg_, geo_] := (AddGeometry[scg, tfg, #] & /@ geo)

который я тестировал

 c1 = {4, {"GE", {"CU", {{0, 0, 0}, 4}}}, 5, 2};
 g = {{4, {"GE", {"CU", {{0, 0, 0}, 4}}}, 5, 
2}, {7, {"GE", {"CU", {{0, 3, 0}, 1}}}, 5, 
2}, {12, {"GE", {"CU", {{0, 5, 0}, 2}}}, 5, 2}};

AddGeometry[scg, tfg, c1]
AddGeometry[scg, tfg, g]

что дало

AddAsChild[scg, tfg, {4, {"GE", {"CU", {{0, 0, 0}, 4}}}, 5, 2}]

и

 {AddAsChild[scg, tfg, {4, {"GE", {"CU", {{0, 0, 0}, 4}}}, 5, 2}], 
 AddAsChild[scg, tfg, {7, {"GE", {"CU", {{0, 3, 0}, 1}}}, 5, 2}], 
  AddAsChild[scg, tfg, {12, {"GE", {"CU", {{0, 5, 0}, 2}}}, 5, 2}]}

Кроме того, если AddAsChild работает исключительно с побочными эффектами, можно использовать Scan вместо Map, чтобы избежать получения возвращаемого списка Null (или вместо этого изменить второе определение на AddGeometry[scg_, tfg_, geo_] := (AddGeometry[scg, tfg, #]; & /@ geo)).

person acl    schedule 11.06.2011
comment
Не могли бы вы объяснить второе утверждение? - person nilo de roock; 11.06.2011
comment
@ ndroock1 Я думаю, вы имеете в виду первое утверждение [я изменил порядок, так как это было неправильно :)] geo_List сопоставляет объекты с головным списком, а затем определение просто отображает ваш AddGeometry (который теперь является вторым утверждением) по списку. Если третий аргумент не является списком, первое определение не соответствует и пробуется второе. Кстати, вам действительно нужен HoldAll? мне кажется без него было бы проще - person acl; 11.06.2011
comment
@ndroock1, кстати, AddGeometry[scg, tfg, #] & /@ geo совпадает с Map[AddGeometry[scg, tfg, #] &, geo] - person acl; 11.06.2011
comment
Потому что это не работает. Обратите внимание, что AddGeometry — это функция в пакете. Вы включили бит SetAttributes? - person nilo de roock; 11.06.2011
comment
Прежде всего, разница в том, что я определил AddGeometry в пакете. Вы уверены, что это можно поместить в пакет? AddGeometry[scg_, tfg_, geo_List] := AddGeometry[scg, tfg, #] & /@ geo Потому что я получаю много сообщений об ошибках. Должен выйти сейчас. #$*^&$* Мы поработаем над этим позже. Спасибо за помощь, софер. - person nilo de roock; 11.06.2011
comment
@ ndroock1 В принципе, поместить его в пакет не должно быть проблемой (т. Е. Если он работал в вашей версии, он должен был работать и в версии, которую я даю). Но кто знает? Может быть, вы можете дать более подробную информацию. - person acl; 11.06.2011
comment
@ ndroock1 см. новую попытку в моем ответе ... если это не сработает, не могли бы вы объяснить, что там не происходит, что должно было быть? мне кажется, что результат, который я получаю, является желаемым; если нет, то не могли бы вы объяснить, почему? - person acl; 12.06.2011
comment
Итак, вы предлагаете мне добавить это в текущий код /; MatchQ[geo, {, {GE, __}, __}]; А затем добавьте эту строку AddGeometry[scg, tfg_, geo_] := (AddGeometry[scg, tfg, #] & /@geo) В приватный раздел. В публичной части изменений нет. Я попробую это сейчас. - person nilo de roock; 12.06.2011
comment
Я сделал опечатку. Он по-прежнему не работает, но странных ошибок мма больше нет. Может быть, я смогу заставить это тоже работать. Доложит. - person nilo de roock; 12.06.2011
comment
@ ndroock1: может быть, будет полезно, если вы также объясните, почему это не удается. насколько я могу судить, поведение, которое я показываю в своем ответе, правильное, не так ли? это не правильно и вы ожидаете чего-то другого? - person acl; 12.06.2011
comment
@acl. Вы использовали функции в пакете? Потому что это может объяснить различия. - person nilo de roock; 12.06.2011
comment
@acl. Много недопонимания из-за использования пакета, но ваше решение работает (после небольшой модификации) и отредактировано в вопросе. Я не совсем уверен, что это то улучшение, которое я искал. Что вы думаете? Сравнение двух? - person nilo de roock; 12.06.2011
comment
@ ndroock1 Я думаю, это концептуально чище, но я чувствую, что ваши структуры могут быть изменены, чтобы сделать вещи менее зависимыми от магических структур (например, все это сломается, если вы измените способ определения георек, например, чтобы расширить свою программу). но не видя остального кода, кто знает (и в любом случае, это обсуждение становится слишком сложным, чтобы вести его в виде комментариев!). в любом случае, хорошо, что это наконец работает! - person acl; 12.06.2011
comment
@acl - Ага. Глядя на это немного дольше, вы определяете. улучшил код. Строку соответствия можно сделать короче. Я поддерживаю граф с различными типами узлов в одном списке, очистка которого на потом. - person nilo de roock; 12.06.2011

Извините, я опубликовал бесполезное «решение» ранее, не подумав. Вы можете попробовать:

ClearAll[AddGeometry]

SetAttributes[AddGeometry, HoldAll];

grpat = {_, {"GE", __}, __};

AddGeometry[scg_, tfg_, geo_] /; Head[geo] === List := 
 AddAsChild[scg, tfg, #] & /@ 
  Quiet[geo /. (x : grpat) | {x : grpat ..} :> {x}]

Который позволяет:

records =
  {{4, {"GE", {"CU", {{0, 0, 0}, 4}}}, 5, 2},
   {3, {"GE", {"CU", {{0, 1, 2}, 4}}}, 7, 1}};

AddGeometry[scg, tfg, records]

(* Out =
{AddAsChild[scg, tfg, {4, {"GE", {"CU", {{0, 0, 0}, 4}}}, 5, 2}], 
 AddAsChild[scg, tfg, {3, {"GE", {"CU", {{0, 1, 2}, 4}}}, 7, 1}]}
*)

Если вам не нужен вывод из AddGeometry, вы можете использовать Scan вместо Map.

person Mr.Wizard    schedule 11.06.2011
comment
Мой собственный ответ работает, но на мой вкус слишком грязный. Все, что я хочу, это если geo содержит «запрос» «записей», то есть несколько записей, а затем распаковывает и обрабатывает их одну за другой. Желательно в стиле Mathematica, чтобы список распознавался и т.д. и т.п. Итак, AddGeometry[scg_, tfg_, geo_] /; Head[geo] === List := не работает в данном ответе. - person nilo de roock; 12.06.2011
comment
Моя ошибка/недоразумение может быть связана с SetAttributes HoldAll, я не уверен. Переменная scg представляет собой (читается: в конечном итоге будет) набор записей, считанных из внешнего файла. Scg будет прочитан пользователем в ноутбуке. Обслуживание scg осуществляется функциями в пакете. То же самое верно и для tfg, который является подмножеством файла. Geo будет содержать новые данные, созданные пользователем в сеансе Notebook. - person nilo de roock; 12.06.2011
comment
@ ndroock1, возможно, вы можете уточнить свой вопрос и привести примеры желаемого результата для данного ввода? на данный момент все немного запутано. - person acl; 12.06.2011