Запись ++ макрос в языке Common LISP

Я написал этот класс, чтобы преодолеть проблему, которую я имел с выбором опции в списке выбора html. Я надеюсь, что это кому-то поможет.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;

namespace Login_page.Models
{
    public class HTMLSelect
    {
        public string id { get; set; }
        public IEnumerable<string> @class { get; set; }
        public string name { get; set; }
        public Boolean required { get; set; }
        public string size { get; set; }
        public IEnumerable<SelectOption> SelectOptions { get; set; }

        public HTMLSelect(IEnumerable<SelectOption> options)
        {

        }

        public HTMLSelect(string id, string name)
        {
            this.id = id;
            this.name = name;
        }

        public HTMLSelect(string id, string name, bool required, IEnumerable<SelectOption> options)
        {
            this.id = id;
            this.name = name;
            this.required = required;
        }

        private string BuildOpeningTag()
        {
            StringBuilder text = new StringBuilder();
            text.Append("<select");
            text.Append(this.id != null ? " id=" + '"' + this.id + '"' : "");
            text.Append(this.name != null ? " name=" + '"' + this.name + '"' : "");
            text.Append(">");
            return text.ToString();

        }

        public string GenerateSelect(IEnumerable<SelectOption> options)
        {
            StringBuilder selectElement = new StringBuilder();
            selectElement.Append(this.BuildOpeningTag());
            foreach (SelectOption option in options)
            {
                StringBuilder text = new StringBuilder();
                text.Append("\t");
                text.Append("<option value=" + '"' + option.Value + '"');
                text.Append(option.Selected != false ? " selected=" + '"' + "selected" + '"' + ">" : ">");
                text.Append(option.Text);
                text.Append("</option>");
                selectElement.Append(text.ToString());
            }
            selectElement.Append("</select");
            return selectElement.ToString();
        }
    }

    public class SelectOption
    {
        public string Text { get; set; }
        public Boolean Selected { get; set; }
        public string Value { get; set; }
    }
}

И

public IEnumerable<SelectOption> getOrderTypes()
{
    List<SelectOption> orderTypes = new List<SelectOption>();
                        if (this.orderType == "OptionText")
                        {
                            orderTypes.Add(new SelectOption() { Value = "1", Text = "OptionText", Selected = true });
                        } else
                        {
                            orderTypes.Add(new SelectOption() { Value = "2", Text = "OptionText2" });
                        }
}

И использовать его:

@{
    Login_page.Models.HTMLSelect selectElement = new Login_page.Models.HTMLSelect("order-types", "order-types");

}
@Html.Raw(selectElement.GenerateSelect(Model.getOrderTypes()));
6
задан Múna 20 March 2014 в 16:57
поделиться

6 ответов

Помните, что макрос возвращает выражение, которое будет оценено. Чтобы сделать это, Вы имеете к одинарной левой кавычке:

(defmacro ++ (variable)
   `(incf ,variable))
17
ответ дан 8 December 2019 в 02:03
поделиться

Обе из предыдущей работы ответов, но они дают Вам макрос, который Вы называете как

(++ varname)

вместо varname ++ или ++ varname, который я подозреваю, Вы хотите. Я не знаю, можно ли на самом деле получить первого, но для последнего, можно сделать макрос чтения. Так как это - два символа, макрос отправки является, вероятно, лучшим. Непротестированный, так как у меня нет удобной рабочей шепелявости, но чего-то как:

(defun plusplus-reader (stream subchar arg)
   (declare (ignore subchar arg))
   (list 'incf (read stream t nil t)))
(set-dispatch-macro-character #\+ #\+ #'plusplus-reader)

должен сделать ++ var на самом деле чтение как (incf var).

12
ответ дан 8 December 2019 в 02:03
поделиться

Семантически, префиксные операторы ++ и - на языке как C++ или независимо от того, что эквивалентный incf/decf в языке Common LISP. Если Вы понимаете это и, как Ваш (неправильный) макрос, на самом деле ищете синтаксическое изменение затем, Вас уже показали, как сделать это с обратными галочками как' (incf, x). Вас даже показали, как заставить читателя бездельничать это, чтобы заставить что-то ближе не шепелявить синтаксис. Это - протирание, хотя, поскольку ни одной из этих вещей не является хорошая идея. В целом не идиоматическое кодирование, чтобы заставить язык напомнить другого более тесно просто не оказывается такой хорошей идеей.

Однако, если на самом деле ищут семантику, Вы уже получили версии префикса, как отмечено, но постфиксные версии не будут легкими соответствовать синтаксически. Вы могли сделать это с достаточным хакерством читателя, но это не будет симпатично.

Если это - то, что Вы ищете, я предложил бы a) палку с именами incf/decf, так как они идиоматичны и работают хорошо и b) запись post-incf, post-decf версии, например, (defmacro post-incf (x) '(prog1, x (incf, x)) виды вещей.

Лично, я не вижу, как это было бы особенно полезно, но ymmv.

7
ответ дан 8 December 2019 в 02:03
поделиться

Для преинкремента, уже существует incf, но можно определить собственное с

(define-modify-macro my-incf () 1+)

Для постинкремента Вы могли использовать это (от тарифа-utils):

(defmacro define-values-post-modify-macro (name val-vars lambda-list function)
 "Multiple-values variant on define-modify macro, to yield pre-modification values"
 (let ((env (gensym "ENV")))
   `(defmacro ,name (,@val-vars ,@lambda-list &environment ,env)
      (multiple-value-bind (vars vals store-vars writer-form reader-form)
          (get-setf-expansion `(values ,,@val-vars) ,env)
       (let ((val-temps (mapcar #'(lambda (temp) (gensym (symbol-name temp)))
                                 ',val-vars)))
          `(let* (,@(mapcar #'list vars vals)
                  ,@store-vars)
             (multiple-value-bind ,val-temps ,reader-form
               (multiple-value-setq ,store-vars
                 (,',function ,@val-temps ,,@lambda-list))
               ,writer-form
               (values ,@val-temps))))))))

(defmacro define-post-modify-macro (name lambda-list function)
 "Variant on define-modify-macro, to yield pre-modification values"
 `(define-values-post-modify-macro ,name (,(gensym)) ,lambda-list ,function))

(define-post-modify-macro post-incf () 1+)
4
ответ дан 8 December 2019 в 02:03
поделиться

Я категорически не рекомендовал бы создание псевдонима для incf. Это уменьшило бы удобочитаемость для кого-либо еще читающего Ваш код, кто должен спросить себя, "что это? как это отличается от incf?"

Если Вы хотите простой постинкремент, попробуйте это:

(defmacro post-inc (number &optional (delta 1))
  "Returns the current value of number, and afterwards increases it by delta (default 1)."
  (let ((value (gensym)))
    `(let ((,value ,number))
       (incf ,number ,delta)
       ,value)))
9
ответ дан 8 December 2019 в 02:03
поделиться

Это должно добиться цели, однако я не гуру шепелявости.

(defmacro ++ (variable)
  `(setq ,variable (+ ,variable 1)))
-2
ответ дан 8 December 2019 в 02:03
поделиться